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

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: Address Ryan's comments Created 8 years, 7 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/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/synchronization/lock.h"
12 #include "base/threading/thread.h"
13 #include "net/proxy/proxy_config.h"
14 #include "net/proxy/proxy_config_service_android.h"
15 #include "net/proxy/proxy_info.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace net {
19
20 namespace {
21
22 typedef std::map<std::string, std::string> StringMap;
23
24 class TestDelegate : public ProxyConfigServiceAndroid::Delegate {
25 public:
26 TestDelegate() : service_(NULL) {}
27
28 // ProxyConfigServiceAndroid::Delegate:
29 virtual void Start(ProxyConfigServiceAndroid* service) OVERRIDE {
30 base::AutoLock lock(lock_);
31 service_ = service;
32 MessageLoop::current()->Quit();
33 }
34
35 virtual void Stop() OVERRIDE {}
36
37 virtual std::string GetProperty(const std::string& property) OVERRIDE {
38 base::AutoLock lock(lock_);
39 StringMap::iterator it = properties_.find(property);
40 if (it == properties_.end())
41 return "";
42 return it->second;
43 }
44
45 // For testing:
46 void SetProperties(const StringMap& properties) {
47 {
48 base::AutoLock lock(lock_);
49 properties_ = properties;
50 }
51 DCHECK(service_);
52 service_->ProxySettingsChangedInternal();
53 }
54
55 private:
56 base::Lock lock_;
57 StringMap properties_;
58 ProxyConfigServiceAndroid* service_;
59 };
60
61 class TestObserver : public ProxyConfigService::Observer {
62 public:
63 TestObserver() : main_thread_loop_(MessageLoop::current()) {}
64
65 // ProxyConfigService::Observer:
66 virtual void OnProxyConfigChanged(
67 const ProxyConfig& config,
68 ProxyConfigService::ConfigAvailability availability) OVERRIDE {
69 // Called from network thread.
70 main_thread_loop_->PostTask(
71 FROM_HERE,
72 base::Bind(&TestObserver::UpdateConfig,
73 base::Unretained(this), config, availability));
74 }
75
76 ProxyConfigService::ConfigAvailability availability() const {
77 return availability_;
78 }
79
80 const ProxyConfig& config() const {
81 return config_;
82 }
83
84 private:
85 void UpdateConfig(const ProxyConfig& config,
86 ProxyConfigService::ConfigAvailability availability) {
87 config_ = config;
88 availability_ = availability;
89 main_thread_loop_->Quit();
90 }
91
92 MessageLoop* const main_thread_loop_;
93 ProxyConfig config_;
94 ProxyConfigService::ConfigAvailability availability_;
95 };
96
97 class TestNetworkThread
98 : public base::Thread,
99 public base::RefCountedThreadSafe<TestNetworkThread> {
100 public:
101 TestNetworkThread(ProxyConfigService::Observer* observer)
102 : base::Thread("network_thread"),
103 observer_(observer) {
104 }
105
106 virtual void CleanUp() OVERRIDE {
107 DCHECK(service_.get());
108 service_->RemoveObserver(observer_);
109 service_.reset();
110 }
111
112 // Takes ownership of |service|.
113 void SetService(ProxyConfigServiceAndroid* service) {
114 service_.reset(service);
115 // Call AddObserver() on the network thread now that the service is set.
116 message_loop_proxy()->PostTask(
117 FROM_HERE, base::Bind(&TestNetworkThread::AddObserver, this));
118 }
119
120 private:
121 friend class base::RefCountedThreadSafe<TestNetworkThread>;
122
123 virtual ~TestNetworkThread() {
124 // This is needed to make sure that CleanUp() is called. See
125 // base::Thread::~Thread() for details.
126 base::Thread::Stop();
127 }
128
129 void AddObserver() {
130 service_->AddObserver(observer_);
131 }
132
133 scoped_ptr<ProxyConfigServiceAndroid> service_;
134 ProxyConfigService::Observer* const observer_;
135 };
136
137 std::string ToString(const ProxyInfo& proxy_info) {
138 ProxyInfo proxy_info_copy(proxy_info);
139 BoundNetLog net_log;
140 std::string result;
141 while (!proxy_info_copy.is_empty()) {
142 if (!result.empty())
143 result += ";";
144 if (!proxy_info_copy.is_direct())
145 result += proxy_info_copy.proxy_server().host_port_pair().ToString();
146 proxy_info_copy.Fallback(net_log);
147 }
148 return result;
149 }
150
151 } // namespace
152
153 class ProxyConfigServiceAndroidTest : public testing::Test {
154 protected:
155 ProxyConfigServiceAndroidTest() : service_(NULL) {}
156
157 // testing::Test:
158 virtual void SetUp() OVERRIDE {
159 configuration_.clear();
160 // Note that |service_| takes ownership of |delegate_|.
161 delegate_ = new TestDelegate();
162 observer_.reset(new TestObserver());
163 network_thread_ = new TestNetworkThread(observer_.get());
164 // Start the network thread now so that its message loop (used below) is
165 // initialized.
166 network_thread_->Start();
167 service_ = new ProxyConfigServiceAndroid(
168 network_thread_->message_loop_proxy(),
169 // JNI thread = main thread.
170 MessageLoop::current()->message_loop_proxy(),
171 delegate_);
172 // Note that |network_thread_| takes ownership of |service_|.
173 network_thread_->SetService(service_);
174 // Run Delegate::Start() which was posted on the current thread.
175 MessageLoop::current()->Run();
176 }
177
178 void TestMapping(const std::string& url, const std::string& expected) {
179 ProxyConfig config;
180 EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
181 service_->GetLatestProxyConfig(&config));
182 ProxyInfo proxy_info;
183 config.proxy_rules().Apply(GURL(url), &proxy_info);
184 EXPECT_EQ(expected, ToString(proxy_info));
185 }
186
187 scoped_ptr<TestObserver> observer_;
188 TestDelegate* delegate_;
189 ProxyConfigServiceAndroid* service_;
190 scoped_refptr<TestNetworkThread> network_thread_;
191 StringMap configuration_;
192 };
193
194 TEST_F(ProxyConfigServiceAndroidTest, TestChangePropertiesNotification) {
195 // Set up a non-empty configuration
196 StringMap properties;
197 properties["http.proxyHost"] = "localhost";
198 delegate_->SetProperties(properties);
199 // Run TestObserver::UpdateConfig() which was posted on the current thread.
200 MessageLoop::current()->Run();
201 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_->availability());
202 EXPECT_FALSE(observer_->config().proxy_rules().empty());
203
204 // Set up an empty configuration
205 delegate_->SetProperties(StringMap());
206 MessageLoop::current()->Run();
207 EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_->availability());
208 EXPECT_TRUE(observer_->config().proxy_rules().empty());
209 }
210
211 // !! The following test cases are automatically generated from
212 // !! net/android/tools/proxy_test_cases.py.
213 // !! Please edit that file instead of editing the test cases below and
214 // !! update also the corresponding Java unit tests in
215 // !! AndroidProxySelectorTest.java
216
217 TEST_F(ProxyConfigServiceAndroidTest, NoProxy) {
218 // Test direct mapping when no proxy defined.
219 delegate_->SetProperties(configuration_);
220 TestMapping("ftp://example.com/", "");
221 TestMapping("http://example.com/", "");
222 TestMapping("https://example.com/", "");
223 }
224
225 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPort) {
226 // Test http.proxyHost and http.proxyPort works.
227 configuration_["http.proxyHost"] = "httpproxy.com";
228 configuration_["http.proxyPort"] = "8080";
229 delegate_->SetProperties(configuration_);
230 TestMapping("ftp://example.com/", "");
231 TestMapping("http://example.com/", "httpproxy.com:8080");
232 TestMapping("https://example.com/", "");
233 }
234
235 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostOnly) {
236 // We should get the default port (80) for proxied hosts.
237 configuration_["http.proxyHost"] = "httpproxy.com";
238 delegate_->SetProperties(configuration_);
239 TestMapping("ftp://example.com/", "");
240 TestMapping("http://example.com/", "httpproxy.com:80");
241 TestMapping("https://example.com/", "");
242 }
243
244 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyPortOnly) {
245 // http.proxyPort only should not result in any hosts being proxied.
246 configuration_["http.proxyPort"] = "8080";
247 delegate_->SetProperties(configuration_);
248 TestMapping("ftp://example.com/", "");
249 TestMapping("http://example.com/", "");
250 TestMapping("https://example.com/", "");
251 }
252
253 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts1) {
254 // Test that HTTP non proxy hosts are mapped correctly
255 configuration_["http.nonProxyHosts"] = "slashdot.org";
256 configuration_["http.proxyHost"] = "httpproxy.com";
257 configuration_["http.proxyPort"] = "8080";
258 delegate_->SetProperties(configuration_);
259 TestMapping("http://example.com/", "httpproxy.com:8080");
260 TestMapping("http://slashdot.org/", "");
261 }
262
263 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts2) {
264 // Test that | pattern works.
265 configuration_["http.nonProxyHosts"] = "slashdot.org|freecode.net";
266 configuration_["http.proxyHost"] = "httpproxy.com";
267 configuration_["http.proxyPort"] = "8080";
268 delegate_->SetProperties(configuration_);
269 TestMapping("http://example.com/", "httpproxy.com:8080");
270 TestMapping("http://freecode.net/", "");
271 TestMapping("http://slashdot.org/", "");
272 }
273
274 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts3) {
275 // Test that * pattern works.
276 configuration_["http.nonProxyHosts"] = "*example.com";
277 configuration_["http.proxyHost"] = "httpproxy.com";
278 configuration_["http.proxyPort"] = "8080";
279 delegate_->SetProperties(configuration_);
280 TestMapping("http://example.com/", "");
281 TestMapping("http://slashdot.org/", "httpproxy.com:8080");
282 TestMapping("http://www.example.com/", "");
283 }
284
285 TEST_F(ProxyConfigServiceAndroidTest, FtpNonProxyHosts) {
286 // Test that FTP non proxy hosts are mapped correctly
287 configuration_["ftp.nonProxyHosts"] = "slashdot.org";
288 configuration_["ftp.proxyHost"] = "httpproxy.com";
289 configuration_["ftp.proxyPort"] = "8080";
290 delegate_->SetProperties(configuration_);
291 TestMapping("ftp://example.com/", "httpproxy.com:8080");
292 TestMapping("http://example.com/", "");
293 }
294
295 TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostAndPort) {
296 // Test ftp.proxyHost and ftp.proxyPort works.
297 configuration_["ftp.proxyHost"] = "httpproxy.com";
298 configuration_["ftp.proxyPort"] = "8080";
299 delegate_->SetProperties(configuration_);
300 TestMapping("ftp://example.com/", "httpproxy.com:8080");
301 TestMapping("http://example.com/", "");
302 TestMapping("https://example.com/", "");
303 }
304
305 TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostOnly) {
306 // Test ftp.proxyHost and default port.
307 configuration_["ftp.proxyHost"] = "httpproxy.com";
308 delegate_->SetProperties(configuration_);
309 TestMapping("ftp://example.com/", "httpproxy.com:80");
310 TestMapping("http://example.com/", "");
311 TestMapping("https://example.com/", "");
312 }
313
314 TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostAndPort) {
315 // Test https.proxyHost and https.proxyPort works.
316 configuration_["https.proxyHost"] = "httpproxy.com";
317 configuration_["https.proxyPort"] = "8080";
318 delegate_->SetProperties(configuration_);
319 TestMapping("ftp://example.com/", "");
320 TestMapping("http://example.com/", "");
321 TestMapping("https://example.com/", "httpproxy.com:8080");
322 }
323
324 TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostOnly) {
325 // Test https.proxyHost and default port.
326 configuration_["https.proxyHost"] = "httpproxy.com";
327 delegate_->SetProperties(configuration_);
328 TestMapping("ftp://example.com/", "");
329 TestMapping("http://example.com/", "");
330 TestMapping("https://example.com/", "httpproxy.com:443");
331 }
332
333 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostIPv6) {
334 // Test IPv6 https.proxyHost and default port.
335 configuration_["http.proxyHost"] = "a:b:c::d:1";
336 delegate_->SetProperties(configuration_);
337 TestMapping("ftp://example.com/", "");
338 TestMapping("http://example.com/", "[a:b:c::d:1]:80");
339 }
340
341 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPortIPv6) {
342 // Test IPv6 http.proxyHost and http.proxyPort works.
343 configuration_["http.proxyHost"] = "a:b:c::d:1";
344 configuration_["http.proxyPort"] = "8080";
345 delegate_->SetProperties(configuration_);
346 TestMapping("ftp://example.com/", "");
347 TestMapping("http://example.com/", "[a:b:c::d:1]:8080");
348 }
349
350 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndInvalidPort) {
351 // Test invalid http.proxyPort does not crash.
352 configuration_["http.proxyHost"] = "a:b:c::d:1";
353 configuration_["http.proxyPort"] = "65536";
354 delegate_->SetProperties(configuration_);
355 TestMapping("ftp://example.com/", "");
356 TestMapping("http://example.com/", "");
357 }
358
359 TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyExplictPort) {
360 // Default http proxy is used if a scheme-specific one is not found.
361 configuration_["ftp.proxyHost"] = "httpproxy.com";
362 configuration_["ftp.proxyPort"] = "8080";
363 configuration_["proxyHost"] = "defaultproxy.com";
364 configuration_["proxyPort"] = "8080";
365 delegate_->SetProperties(configuration_);
366 TestMapping("ftp://example.com/", "httpproxy.com:8080");
367 TestMapping("http://example.com/", "defaultproxy.com:8080");
368 TestMapping("https://example.com/", "defaultproxy.com:8080");
369 }
370
371 TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyDefaultPort) {
372 // Check that the default proxy port is as expected.
373 configuration_["proxyHost"] = "defaultproxy.com";
374 delegate_->SetProperties(configuration_);
375 TestMapping("http://example.com/", "defaultproxy.com:80");
376 TestMapping("https://example.com/", "defaultproxy.com:443");
377 }
378
379 TEST_F(ProxyConfigServiceAndroidTest, FallbackToSocks) {
380 // SOCKS proxy is used if scheme-specific one is not found.
381 configuration_["http.proxyHost"] = "defaultproxy.com";
382 configuration_["socksProxyHost"] = "socksproxy.com";
383 delegate_->SetProperties(configuration_);
384 TestMapping("ftp://example.com", "socksproxy.com:1080");
385 TestMapping("http://example.com/", "defaultproxy.com:80");
386 TestMapping("https://example.com/", "socksproxy.com:1080");
387 }
388
389 TEST_F(ProxyConfigServiceAndroidTest, SocksExplicitPort) {
390 // SOCKS proxy port is used if specified
391 configuration_["socksProxyHost"] = "socksproxy.com";
392 configuration_["socksProxyPort"] = "9000";
393 delegate_->SetProperties(configuration_);
394 TestMapping("http://example.com/", "socksproxy.com:9000");
395 }
396
397 TEST_F(ProxyConfigServiceAndroidTest, HttpProxySupercedesSocks) {
398 // SOCKS proxy is ignored if default HTTP proxy defined.
399 configuration_["proxyHost"] = "defaultproxy.com";
400 configuration_["socksProxyHost"] = "socksproxy.com";
401 configuration_["socksProxyPort"] = "9000";
402 delegate_->SetProperties(configuration_);
403 TestMapping("http://example.com/", "defaultproxy.com:80");
404 }
405
406 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698