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

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

Powered by Google App Engine
This is Rietveld 408576698