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

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

Powered by Google App Engine
This is Rietveld 408576698