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

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

Issue 10206014: Upstream Android proxy config service. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix comment Created 8 years, 6 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 <map>
6 #include <string>
7
8 #include "base/bind.h"
9 #include "base/compiler_specific.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/thread.h"
15 #include "net/proxy/proxy_config.h"
16 #include "net/proxy/proxy_config_service_android.h"
17 #include "net/proxy/proxy_info.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace net {
21
22 namespace {
23
24 scoped_ptr<base::WaitableEvent> MakeWaitableEvent() {
25 return scoped_ptr<base::WaitableEvent>(
26 new base::WaitableEvent(
27 false /* automatic reset */, false /* not signaled initialy */));
28 }
29
30 class TestObserver : public ProxyConfigService::Observer {
31 public:
32 TestObserver(base::WaitableEvent* proxy_config_changed_event)
33 : main_thread_loop_(MessageLoop::current()),
34 proxy_config_changed_event_(proxy_config_changed_event) {}
35
36 // ProxyConfigService::Observer:
37 virtual void OnProxyConfigChanged(
38 const ProxyConfig& config,
39 ProxyConfigService::ConfigAvailability availability) OVERRIDE {
40 // Called from network thread.
41 main_thread_loop_->PostTask(
42 FROM_HERE,
43 base::Bind(&TestObserver::UpdateConfig,
44 base::Unretained(this), config, availability));
45 proxy_config_changed_event_->Signal();
46 }
47
48 // Called from main thread.
49 ProxyConfigService::ConfigAvailability availability() const {
50 return availability_;
51 }
52
53 const ProxyConfig& config() const {
54 return config_;
55 }
56
57 private:
58 void UpdateConfig(const ProxyConfig& config,
59 ProxyConfigService::ConfigAvailability availability) {
60 config_ = config;
61 availability_ = availability;
62 main_thread_loop_->Quit();
63 }
64
65 MessageLoop* const main_thread_loop_;
66 base::WaitableEvent* const proxy_config_changed_event_;
67 // Accessed only from the main thread.
68 ProxyConfig config_;
69 ProxyConfigService::ConfigAvailability availability_;
70 };
71
72 std::string ToString(const ProxyInfo& proxy_info) {
73 ProxyInfo proxy_info_copy(proxy_info);
74 BoundNetLog net_log;
75 std::string result;
76 while (!proxy_info_copy.is_empty()) {
77 if (!result.empty())
78 result += ";";
79 if (!proxy_info_copy.is_direct())
80 result += proxy_info_copy.proxy_server().host_port_pair().ToString();
81 proxy_info_copy.Fallback(net_log);
82 }
83 return result;
Ryan Sleevi 2012/05/25 17:42:14 Use ProxyInfo.ToPacString() - this whole loop is a
Philippe 2012/05/29 10:05:30 Done.
84 }
85
86 } // namespace
87
88 class ProxyConfigServiceAndroidTest : public testing::Test {
89 protected:
90 ProxyConfigServiceAndroidTest() : service_(NULL) {}
91
92 typedef std::map<std::string, std::string> StringMap;
93
94 // testing::Test:
95 virtual void SetUp() OVERRIDE {
96 proxy_config_changed_event_ = MakeWaitableEvent();
97 observer_.reset(new TestObserver(proxy_config_changed_event_.get()));
98
99 jni_thread_.reset(new base::Thread("jni_thread"));
100 network_thread_.reset(new base::Thread("network_thread"));
101
102 jni_thread_->Start();
103 network_thread_->Start();
104
105 ClearConfiguration();
106 service_.reset(new ProxyConfigServiceAndroid(
107 network_thread_->message_loop_proxy(),
108 jni_thread_->message_loop_proxy(),
109 base::Bind(&ProxyConfigServiceAndroidTest::GetPropertyOnJNIThread,
110 base::Unretained(this))));
111
112 AddObserver();
113 }
114
115 virtual void TearDown() OVERRIDE {
116 service_.reset();
117 network_thread_.reset();
118 jni_thread_.reset();
119 proxy_config_changed_event_.reset();
120 }
121
122 void AddProperty(const std::string& key, const std::string& value) {
123 jni_thread_->message_loop_proxy()->PostTask(
124 FROM_HERE,
125 base::Bind(&ProxyConfigServiceAndroidTest::AddPropertyOnJNIThread,
126 base::Unretained(this), key, value));
127 }
128
129 void ClearConfiguration() {
130 jni_thread_->message_loop_proxy()->PostTask(
131 FROM_HERE,
132 base::Bind(&StringMap::clear, base::Unretained(&configuration_)));
133 }
134
135 void ProxySettingsChanged() {
136 jni_thread_->message_loop_proxy()->PostTask(
137 FROM_HERE,
138 base::Bind(&ProxyConfigServiceAndroid::ProxySettingsChanged,
139 base::Unretained(service_.get()), static_cast<JNIEnv*>(NULL),
140 static_cast<jobject>(NULL)));
141 proxy_config_changed_event_->Wait();
142 MessageLoop::current()->Run();
143 }
144
145 ProxyConfigService::ConfigAvailability GetLatestProxyConfig(
146 ProxyConfig* proxy_config) {
147 // Post ProxyConfigServiceAndroid::GetLatestProxyConfig() on the network
148 // thread and wait for its completion.
149 scoped_ptr<base::WaitableEvent> completion_event(MakeWaitableEvent());
150 ProxyConfigService::ConfigAvailability availability;
151 network_thread_->message_loop_proxy()->PostTask(
152 FROM_HERE,
153 base::Bind(
154 &ProxyConfigServiceAndroidTest::GetLatestProxyConfigOnNetworkThread,
155 base::Unretained(this), proxy_config, &availability,
156 completion_event.get()));
157 completion_event->Wait();
158 return availability;
159 }
160
161 void TestMapping(const std::string& url, const std::string& expected) {
162 ProxyConfig proxy_config = observer_->config();
163 TestMappingForProxyConfig(
164 url, expected, observer_->availability(), &proxy_config);
165 }
166
167 static void TestMappingForProxyConfig(
168 const std::string& url,
169 const std::string& expected,
170 ProxyConfigService::ConfigAvailability availability,
171 ProxyConfig* proxy_config) {
172 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, availability);
173 ProxyInfo proxy_info;
174 proxy_config->proxy_rules().Apply(GURL(url), &proxy_info);
175 EXPECT_EQ(expected, ToString(proxy_info));
176 }
177
178 // Accessed only from the JNI thread.
179 StringMap configuration_;
180
181 scoped_ptr<TestObserver> observer_;
182
183 private:
184 std::string GetPropertyOnJNIThread(const std::string& property) {
185 DCHECK(OnJNIThread());
186 StringMap::const_iterator it = configuration_.find(property);
187 if (it == configuration_.end())
188 return "";
189 return it->second;
190 }
191
192 void AddPropertyOnJNIThread(const std::string& key,
193 const std::string& value) {
194 DCHECK(OnJNIThread());
195 configuration_[key] = value;
196 }
197
198 void AddObserver() {
199 jni_thread_->message_loop_proxy()->PostTask(
200 FROM_HERE,
201 base::Bind(
202 &ProxyConfigServiceAndroidTest::AddObserverAfterInitialConfigIsSet,
203 base::Unretained(this)));
204 }
205
206 void AddObserverAfterInitialConfigIsSet() {
207 DCHECK(OnJNIThread());
208 network_thread_->message_loop_proxy()->PostTask(
209 FROM_HERE,
210 base::Bind(&ProxyConfigServiceAndroid::AddObserver,
211 base::Unretained(service_.get()), observer_.get()));
212 }
213
214 void GetLatestProxyConfigOnNetworkThread(
215 ProxyConfig* proxy_config,
216 ProxyConfigService::ConfigAvailability* availability,
217 base::WaitableEvent* completion_event) {
218 DCHECK(OnNetworkThread());
219 *availability = service_->GetLatestProxyConfig(proxy_config);
220 completion_event->Signal();
221 }
222
223 bool OnJNIThread() const {
224 return jni_thread_->message_loop_proxy()->BelongsToCurrentThread();
225 }
226
227 bool OnNetworkThread() const {
228 return network_thread_->message_loop_proxy()->BelongsToCurrentThread();
229 }
230
231 scoped_ptr<base::WaitableEvent> proxy_config_changed_event_;
232 scoped_ptr<base::Thread> jni_thread_;
233 scoped_ptr<base::Thread> network_thread_;
234 scoped_ptr<ProxyConfigServiceAndroid> service_;
235 };
236
237 TEST_F(ProxyConfigServiceAndroidTest, TestChangePropertiesNotification) {
238 // Set up a non-empty configuration
239 AddProperty("http.proxyHost", "localhost");
240 ProxySettingsChanged();
241 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_->availability());
242 EXPECT_FALSE(observer_->config().proxy_rules().empty());
243
244 // Set up an empty configuration
245 ClearConfiguration();
246 ProxySettingsChanged();
247 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_->availability());
248 EXPECT_TRUE(observer_->config().proxy_rules().empty());
249 }
250
251 TEST_F(ProxyConfigServiceAndroidTest, GetLatestConfigWithoutUsingObserver) {
252 AddProperty("http.proxyHost", "httpproxy.com");
253 AddProperty("http.proxyPort", "8080");
254 ProxySettingsChanged();
255 ProxyConfig proxy_config;
256 ProxyConfigService::ConfigAvailability availability =
257 GetLatestProxyConfig(&proxy_config);
258 TestMappingForProxyConfig(
259 "http://example.com/", "httpproxy.com:8080", availability, &proxy_config);
260 }
261
262 // !! The following test cases are automatically generated from
263 // !! net/android/tools/proxy_test_cases.py.
264 // !! Please edit that file instead of editing the test cases below and
265 // !! update also the corresponding Java unit tests in
266 // !! AndroidProxySelectorTest.java
267
268 TEST_F(ProxyConfigServiceAndroidTest, NoProxy) {
269 // Test direct mapping when no proxy defined.
270 ProxySettingsChanged();
271 TestMapping("ftp://example.com/", "");
272 TestMapping("http://example.com/", "");
273 TestMapping("https://example.com/", "");
274 }
275
276 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPort) {
277 // Test http.proxyHost and http.proxyPort works.
278 AddProperty("http.proxyHost", "httpproxy.com");
279 AddProperty("http.proxyPort", "8080");
280 ProxySettingsChanged();
281 TestMapping("ftp://example.com/", "");
282 TestMapping("http://example.com/", "httpproxy.com:8080");
283 TestMapping("https://example.com/", "");
284 }
285
286 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostOnly) {
287 // We should get the default port (80) for proxied hosts.
288 AddProperty("http.proxyHost", "httpproxy.com");
289 ProxySettingsChanged();
290 TestMapping("ftp://example.com/", "");
291 TestMapping("http://example.com/", "httpproxy.com:80");
292 TestMapping("https://example.com/", "");
293 }
294
295 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyPortOnly) {
296 // http.proxyPort only should not result in any hosts being proxied.
297 AddProperty("http.proxyPort", "8080");
298 ProxySettingsChanged();
299 TestMapping("ftp://example.com/", "");
300 TestMapping("http://example.com/", "");
301 TestMapping("https://example.com/", "");
302 }
303
304 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts1) {
305 // Test that HTTP non proxy hosts are mapped correctly
306 AddProperty("http.nonProxyHosts", "slashdot.org");
307 AddProperty("http.proxyHost", "httpproxy.com");
308 AddProperty("http.proxyPort", "8080");
309 ProxySettingsChanged();
310 TestMapping("http://example.com/", "httpproxy.com:8080");
311 TestMapping("http://slashdot.org/", "");
312 }
313
314 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts2) {
315 // Test that | pattern works.
316 AddProperty("http.nonProxyHosts", "slashdot.org|freecode.net");
317 AddProperty("http.proxyHost", "httpproxy.com");
318 AddProperty("http.proxyPort", "8080");
319 ProxySettingsChanged();
320 TestMapping("http://example.com/", "httpproxy.com:8080");
321 TestMapping("http://freecode.net/", "");
322 TestMapping("http://slashdot.org/", "");
323 }
324
325 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts3) {
326 // Test that * pattern works.
327 AddProperty("http.nonProxyHosts", "*example.com");
328 AddProperty("http.proxyHost", "httpproxy.com");
329 AddProperty("http.proxyPort", "8080");
330 ProxySettingsChanged();
331 TestMapping("http://example.com/", "");
332 TestMapping("http://slashdot.org/", "httpproxy.com:8080");
333 TestMapping("http://www.example.com/", "");
334 }
335
336 TEST_F(ProxyConfigServiceAndroidTest, FtpNonProxyHosts) {
337 // Test that FTP non proxy hosts are mapped correctly
338 AddProperty("ftp.nonProxyHosts", "slashdot.org");
339 AddProperty("ftp.proxyHost", "httpproxy.com");
340 AddProperty("ftp.proxyPort", "8080");
341 ProxySettingsChanged();
342 TestMapping("ftp://example.com/", "httpproxy.com:8080");
343 TestMapping("http://example.com/", "");
344 }
345
346 TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostAndPort) {
347 // Test ftp.proxyHost and ftp.proxyPort works.
348 AddProperty("ftp.proxyHost", "httpproxy.com");
349 AddProperty("ftp.proxyPort", "8080");
350 ProxySettingsChanged();
351 TestMapping("ftp://example.com/", "httpproxy.com:8080");
352 TestMapping("http://example.com/", "");
353 TestMapping("https://example.com/", "");
354 }
355
356 TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostOnly) {
357 // Test ftp.proxyHost and default port.
358 AddProperty("ftp.proxyHost", "httpproxy.com");
359 ProxySettingsChanged();
360 TestMapping("ftp://example.com/", "httpproxy.com:80");
361 TestMapping("http://example.com/", "");
362 TestMapping("https://example.com/", "");
363 }
364
365 TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostAndPort) {
366 // Test https.proxyHost and https.proxyPort works.
367 AddProperty("https.proxyHost", "httpproxy.com");
368 AddProperty("https.proxyPort", "8080");
369 ProxySettingsChanged();
370 TestMapping("ftp://example.com/", "");
371 TestMapping("http://example.com/", "");
372 TestMapping("https://example.com/", "httpproxy.com:8080");
373 }
374
375 TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostOnly) {
376 // Test https.proxyHost and default port.
377 AddProperty("https.proxyHost", "httpproxy.com");
378 ProxySettingsChanged();
379 TestMapping("ftp://example.com/", "");
380 TestMapping("http://example.com/", "");
381 TestMapping("https://example.com/", "httpproxy.com:443");
382 }
383
384 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostIPv6) {
385 // Test IPv6 https.proxyHost and default port.
386 AddProperty("http.proxyHost", "a:b:c::d:1");
387 ProxySettingsChanged();
388 TestMapping("ftp://example.com/", "");
389 TestMapping("http://example.com/", "[a:b:c::d:1]:80");
390 }
391
392 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPortIPv6) {
393 // Test IPv6 http.proxyHost and http.proxyPort works.
394 AddProperty("http.proxyHost", "a:b:c::d:1");
395 AddProperty("http.proxyPort", "8080");
396 ProxySettingsChanged();
397 TestMapping("ftp://example.com/", "");
398 TestMapping("http://example.com/", "[a:b:c::d:1]:8080");
399 }
400
401 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndInvalidPort) {
402 // Test invalid http.proxyPort does not crash.
403 AddProperty("http.proxyHost", "a:b:c::d:1");
404 AddProperty("http.proxyPort", "65536");
405 ProxySettingsChanged();
406 TestMapping("ftp://example.com/", "");
407 TestMapping("http://example.com/", "");
408 }
409
410 TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyExplictPort) {
411 // Default http proxy is used if a scheme-specific one is not found.
412 AddProperty("ftp.proxyHost", "httpproxy.com");
413 AddProperty("ftp.proxyPort", "8080");
414 AddProperty("proxyHost", "defaultproxy.com");
415 AddProperty("proxyPort", "8080");
416 ProxySettingsChanged();
417 TestMapping("ftp://example.com/", "httpproxy.com:8080");
418 TestMapping("http://example.com/", "defaultproxy.com:8080");
419 TestMapping("https://example.com/", "defaultproxy.com:8080");
420 }
421
422 TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyDefaultPort) {
423 // Check that the default proxy port is as expected.
424 AddProperty("proxyHost", "defaultproxy.com");
425 ProxySettingsChanged();
426 TestMapping("http://example.com/", "defaultproxy.com:80");
427 TestMapping("https://example.com/", "defaultproxy.com:443");
428 }
429
430 TEST_F(ProxyConfigServiceAndroidTest, FallbackToSocks) {
431 // SOCKS proxy is used if scheme-specific one is not found.
432 AddProperty("http.proxyHost", "defaultproxy.com");
433 AddProperty("socksProxyHost", "socksproxy.com");
434 ProxySettingsChanged();
435 TestMapping("ftp://example.com", "socksproxy.com:1080");
436 TestMapping("http://example.com/", "defaultproxy.com:80");
437 TestMapping("https://example.com/", "socksproxy.com:1080");
438 }
439
440 TEST_F(ProxyConfigServiceAndroidTest, SocksExplicitPort) {
441 // SOCKS proxy port is used if specified
442 AddProperty("socksProxyHost", "socksproxy.com");
443 AddProperty("socksProxyPort", "9000");
444 ProxySettingsChanged();
445 TestMapping("http://example.com/", "socksproxy.com:9000");
446 }
447
448 TEST_F(ProxyConfigServiceAndroidTest, HttpProxySupercedesSocks) {
449 // SOCKS proxy is ignored if default HTTP proxy defined.
450 AddProperty("proxyHost", "defaultproxy.com");
451 AddProperty("socksProxyHost", "socksproxy.com");
452 AddProperty("socksProxyPort", "9000");
453 ProxySettingsChanged();
454 TestMapping("http://example.com/", "defaultproxy.com:80");
455 }
456
457 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698