| Index: net/proxy/proxy_config_service_android_unittest.cc
|
| diff --git a/net/proxy/proxy_config_service_android_unittest.cc b/net/proxy/proxy_config_service_android_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d986beff1924eeb25d751a725b0849f1c801b158
|
| --- /dev/null
|
| +++ b/net/proxy/proxy_config_service_android_unittest.cc
|
| @@ -0,0 +1,384 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <map>
|
| +#include <string>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/synchronization/lock.h"
|
| +#include "base/threading/platform_thread.h"
|
| +#include "base/threading/thread.h"
|
| +#include "net/proxy/proxy_config.h"
|
| +#include "net/proxy/proxy_config_service_android.h"
|
| +#include "net/proxy/proxy_info.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace {
|
| +
|
| +typedef std::map<std::string, std::string> StringMap;
|
| +
|
| +class TestDelegate : public ProxyConfigServiceAndroid::Delegate {
|
| + public:
|
| + TestDelegate() : service_(NULL) {}
|
| +
|
| + // ProxyConfigServiceAndroid::Delegate:
|
| + virtual void Start(ProxyConfigServiceAndroid* service) OVERRIDE {
|
| + base::AutoLock lock(lock_);
|
| + service_ = service;
|
| + }
|
| +
|
| + virtual void Stop() OVERRIDE {}
|
| +
|
| + virtual std::string GetProperty(const std::string& property) OVERRIDE {
|
| + base::AutoLock lock(lock_);
|
| + StringMap::iterator it = properties_.find(property);
|
| + if (it == properties_.end())
|
| + return "";
|
| + return it->second;
|
| + }
|
| +
|
| + // For testing:
|
| + void SetProperties(const StringMap& properties) {
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + properties_ = properties;
|
| + }
|
| + DCHECK(service_);
|
| + service_->ProxySettingsChanged();
|
| + }
|
| +
|
| + // Waits until Start() is called by the observer thread.
|
| + void WaitUntilReady() {
|
| + while (true) {
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + if (service_)
|
| + return;
|
| + }
|
| + base::PlatformThread::YieldCurrentThread();
|
| + }
|
| + }
|
| +
|
| + private:
|
| + base::Lock lock_;
|
| + StringMap properties_;
|
| + ProxyConfigServiceAndroid* service_;
|
| +};
|
| +
|
| +class TestObserver : public ProxyConfigService::Observer {
|
| + public:
|
| + TestObserver() : main_thread_loop_(MessageLoop::current()) {}
|
| +
|
| + // ProxyConfigService::Observer:
|
| + virtual void OnProxyConfigChanged(
|
| + const ProxyConfig& config,
|
| + ProxyConfigService::ConfigAvailability availability) OVERRIDE {
|
| + // Called from observer thread.
|
| + main_thread_loop_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&TestObserver::UpdateConfig,
|
| + base::Unretained(this), config, availability));
|
| + }
|
| +
|
| + ProxyConfigService::ConfigAvailability availability() const {
|
| + return availability_;
|
| + }
|
| +
|
| + const ProxyConfig& config() const {
|
| + return config_;
|
| + }
|
| +
|
| + private:
|
| + void UpdateConfig(const ProxyConfig& config,
|
| + ProxyConfigService::ConfigAvailability availability) {
|
| + config_ = config;
|
| + availability_ = availability;
|
| + main_thread_loop_->Quit();
|
| + }
|
| +
|
| + MessageLoop* const main_thread_loop_;
|
| + ProxyConfig config_;
|
| + ProxyConfigService::ConfigAvailability availability_;
|
| +};
|
| +
|
| +class TestObserverThread : public base::Thread {
|
| + public:
|
| + TestObserverThread(ProxyConfigService::Observer* observer)
|
| + : base::Thread("observer_thread"),
|
| + observer_(observer) {
|
| + }
|
| +
|
| + virtual ~TestObserverThread() {
|
| + // This is needed to make sure that CleanUp() is called. See
|
| + // base::Thread::~Thread() for details.
|
| + base::Thread::Stop();
|
| + }
|
| +
|
| + virtual void CleanUp() OVERRIDE {
|
| + DCHECK(service_.get());
|
| + service_->RemoveObserver(observer_);
|
| + service_.reset();
|
| + }
|
| +
|
| + // Takes ownership of |service|.
|
| + void SetService(ProxyConfigServiceAndroid* service) {
|
| + service_.reset(service);
|
| + // Call AddObserver() on the observer thread now that the service is set.
|
| + message_loop_proxy()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&TestObserverThread::AddObserver, base::Unretained(this)));
|
| + }
|
| +
|
| + private:
|
| + void AddObserver() {
|
| + service_->AddObserver(observer_);
|
| + }
|
| +
|
| + scoped_ptr<ProxyConfigServiceAndroid> service_;
|
| + ProxyConfigService::Observer* const observer_;
|
| +};
|
| +
|
| +std::string ToString(const ProxyInfo& proxy_info) {
|
| + ProxyInfo proxy_info_copy(proxy_info);
|
| + BoundNetLog net_log;
|
| + std::string result;
|
| + while (!proxy_info_copy.is_empty()) {
|
| + if (!result.empty())
|
| + result += ";";
|
| + if (!proxy_info_copy.is_direct())
|
| + result += proxy_info_copy.proxy_server().host_port_pair().ToString();
|
| + proxy_info_copy.Fallback(net_log);
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class ProxyConfigServiceAndroidTest : public testing::Test {
|
| + protected:
|
| + ProxyConfigServiceAndroidTest() : service_(NULL) {}
|
| +
|
| + // testing::Test
|
| + virtual void SetUp() OVERRIDE {
|
| + configuration_.clear();
|
| + // Note that |service_| takes ownership of |delegate_|.
|
| + delegate_ = new TestDelegate();
|
| + observer_.reset(new TestObserver());
|
| + observer_thread_.reset(new TestObserverThread(observer_.get()));
|
| + // Start the observer thread now so that its message loop (used below) is
|
| + // initialized.
|
| + observer_thread_->Start();
|
| + service_ = new ProxyConfigServiceAndroid(
|
| + observer_thread_->message_loop_proxy(), delegate_);
|
| + // Note that |observer_thread_| takes ownership of |service_|.
|
| + observer_thread_->SetService(service_);
|
| + // Block until the observer thread calls TestDelegate::Start().
|
| + delegate_->WaitUntilReady();
|
| + }
|
| +
|
| + void TestMapping(const std::string& url, const std::string& expected) {
|
| + ProxyConfig config;
|
| + EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
|
| + service_->GetLatestProxyConfig(&config));
|
| + ProxyInfo proxy_info;
|
| + config.proxy_rules().Apply(GURL(url), &proxy_info);
|
| + EXPECT_EQ(expected, ToString(proxy_info));
|
| + }
|
| +
|
| + scoped_ptr<TestObserver> observer_;
|
| + TestDelegate* delegate_;
|
| + ProxyConfigServiceAndroid* service_;
|
| + scoped_ptr<TestObserverThread> observer_thread_;
|
| + StringMap configuration_;
|
| +};
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, TestChangePropertiesNotification) {
|
| + // Set up a non-empty configuration
|
| + StringMap properties;
|
| + properties["http.proxyHost"] = "localhost";
|
| + delegate_->SetProperties(properties);
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_->availability());
|
| + EXPECT_FALSE(observer_->config().proxy_rules().empty());
|
| +
|
| + // Set up an empty configuration
|
| + delegate_->SetProperties(StringMap());
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_->availability());
|
| + EXPECT_TRUE(observer_->config().proxy_rules().empty());
|
| +}
|
| +
|
| +// !! The following test cases are automatically generated from
|
| +// !! net/android/tools/proxy_test_cases.py.
|
| +// !! Please edit that file instead of editing the test cases below and
|
| +// !! update also the corresponding Java unit tests in
|
| +// !! AndroidProxySelectorTest.java
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, NoProxy) {
|
| + // Test direct mapping when no proxy defined.
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "");
|
| + TestMapping("http://example.com/", "");
|
| + TestMapping("https://example.com/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPort) {
|
| + // Test http.proxyHost and http.proxyPort works.
|
| + configuration_["http.proxyHost"] = "httpproxy.com";
|
| + configuration_["http.proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "");
|
| + TestMapping("http://example.com/", "httpproxy.com:8080");
|
| + TestMapping("https://example.com/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostOnly) {
|
| + // We should get the default port (80) for proxied hosts.
|
| + configuration_["http.proxyHost"] = "httpproxy.com";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "");
|
| + TestMapping("http://example.com/", "httpproxy.com:80");
|
| + TestMapping("https://example.com/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpProxyPortOnly) {
|
| + // http.proxyPort only should not result in any hosts being proxied.
|
| + configuration_["http.proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "");
|
| + TestMapping("http://example.com/", "");
|
| + TestMapping("https://example.com/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts1) {
|
| + // Test that HTTP non proxy hosts are mapped correctly
|
| + configuration_["http.nonProxyHosts"] = "slashdot.org";
|
| + configuration_["http.proxyHost"] = "httpproxy.com";
|
| + configuration_["http.proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("http://example.com/", "httpproxy.com:8080");
|
| + TestMapping("http://slashdot.org/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts2) {
|
| + // Test that | pattern works.
|
| + configuration_["http.nonProxyHosts"] = "slashdot.org|freecode.net";
|
| + configuration_["http.proxyHost"] = "httpproxy.com";
|
| + configuration_["http.proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("http://example.com/", "httpproxy.com:8080");
|
| + TestMapping("http://freecode.net/", "");
|
| + TestMapping("http://slashdot.org/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts3) {
|
| + // Test that * pattern works.
|
| + configuration_["http.nonProxyHosts"] = "*example.com";
|
| + configuration_["http.proxyHost"] = "httpproxy.com";
|
| + configuration_["http.proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("http://example.com/", "");
|
| + TestMapping("http://slashdot.org/", "httpproxy.com:8080");
|
| + TestMapping("http://www.example.com/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, FtpNonProxyHosts) {
|
| + // Test that FTP non proxy hosts are mapped correctly
|
| + configuration_["ftp.nonProxyHosts"] = "slashdot.org";
|
| + configuration_["ftp.proxyHost"] = "httpproxy.com";
|
| + configuration_["ftp.proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "httpproxy.com:8080");
|
| + TestMapping("http://example.com/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostAndPort) {
|
| + // Test ftp.proxyHost and ftp.proxyPort works.
|
| + configuration_["ftp.proxyHost"] = "httpproxy.com";
|
| + configuration_["ftp.proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "httpproxy.com:8080");
|
| + TestMapping("http://example.com/", "");
|
| + TestMapping("https://example.com/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostOnly) {
|
| + // Test ftp.proxyHost and default port.
|
| + configuration_["ftp.proxyHost"] = "httpproxy.com";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "httpproxy.com:80");
|
| + TestMapping("http://example.com/", "");
|
| + TestMapping("https://example.com/", "");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostAndPort) {
|
| + // Test https.proxyHost and https.proxyPort works.
|
| + configuration_["https.proxyHost"] = "httpproxy.com";
|
| + configuration_["https.proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "");
|
| + TestMapping("http://example.com/", "");
|
| + TestMapping("https://example.com/", "httpproxy.com:8080");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostOnly) {
|
| + // Test https.proxyHost and default port.
|
| + configuration_["https.proxyHost"] = "httpproxy.com";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "");
|
| + TestMapping("http://example.com/", "");
|
| + TestMapping("https://example.com/", "httpproxy.com:443");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyExplictPort) {
|
| + // Default http proxy is used if a scheme-specific one is not found.
|
| + configuration_["ftp.proxyHost"] = "httpproxy.com";
|
| + configuration_["ftp.proxyPort"] = "8080";
|
| + configuration_["proxyHost"] = "defaultproxy.com";
|
| + configuration_["proxyPort"] = "8080";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com/", "httpproxy.com:8080");
|
| + TestMapping("http://example.com/", "defaultproxy.com:8080");
|
| + TestMapping("https://example.com/", "defaultproxy.com:8080");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyDefaultPort) {
|
| + // Check that the default proxy port is as expected.
|
| + configuration_["proxyHost"] = "defaultproxy.com";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("http://example.com/", "defaultproxy.com:80");
|
| + TestMapping("https://example.com/", "defaultproxy.com:443");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, FallbackToSocks) {
|
| + // SOCKS proxy is used if scheme-specific one is not found.
|
| + configuration_["http.proxyHost"] = "defaultproxy.com";
|
| + configuration_["socksProxyHost"] = "socksproxy.com";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("ftp://example.com", "socksproxy.com:1080");
|
| + TestMapping("http://example.com/", "defaultproxy.com:80");
|
| + TestMapping("https://example.com/", "socksproxy.com:1080");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, SocksExplicitPort) {
|
| + // SOCKS proxy port is used if specified
|
| + configuration_["socksProxyHost"] = "socksproxy.com";
|
| + configuration_["socksProxyPort"] = "9000";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("http://example.com/", "socksproxy.com:9000");
|
| +}
|
| +
|
| +TEST_F(ProxyConfigServiceAndroidTest, HttpProxySupercedesSocks) {
|
| + // SOCKS proxy is ignored if default HTTP proxy defined.
|
| + configuration_["proxyHost"] = "defaultproxy.com";
|
| + configuration_["socksProxyHost"] = "socksproxy.com";
|
| + configuration_["socksProxyPort"] = "9000";
|
| + delegate_->SetProperties(configuration_);
|
| + TestMapping("http://example.com/", "defaultproxy.com:80");
|
| +}
|
| +
|
| +} // namespace net
|
|
|