proxy_config_service_impl_unittest.cc revision 5e3f23d412006dc4db4e659864679f29341e113f
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 "chrome/browser/chromeos/proxy_config_service_impl.h" 6 7#include <vector> 8 9#include "base/format_macros.h" 10#include "base/json/json_writer.h" 11#include "base/logging.h" 12#include "base/message_loop.h" 13#include "base/prefs/testing_pref_service.h" 14#include "base/strings/stringprintf.h" 15#include "chrome/browser/chromeos/settings/cros_settings.h" 16#include "chrome/browser/chromeos/settings/device_settings_service.h" 17#include "chrome/browser/chromeos/ui_proxy_config.h" 18#include "chrome/common/pref_names.h" 19#include "chromeos/dbus/dbus_thread_manager.h" 20#include "chromeos/dbus/shill_profile_client.h" 21#include "chromeos/dbus/shill_service_client.h" 22#include "chromeos/network/network_handler.h" 23#include "chromeos/network/network_state.h" 24#include "chromeos/network/network_state_handler.h" 25#include "content/public/test/test_browser_thread.h" 26#include "net/proxy/proxy_config_service_common_unittest.h" 27#include "testing/gtest/include/gtest/gtest.h" 28#include "third_party/cros_system_api/dbus/service_constants.h" 29 30using content::BrowserThread; 31 32namespace chromeos { 33 34namespace { 35 36struct Input { 37 UIProxyConfig::Mode mode; 38 std::string pac_url; 39 std::string server; 40 std::string bypass_rules; 41}; 42 43// Builds an identifier for each test in an array. 44#define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc) 45 46// Shortcuts to declare enums within chromeos's ProxyConfig. 47#define MK_MODE(mode) UIProxyConfig::MODE_##mode 48 49// Inspired from net/proxy/proxy_config_service_linux_unittest.cc. 50const struct TestParams { 51 // Short description to identify the test 52 std::string description; 53 54 Input input; 55 56 // Expected outputs from fields of net::ProxyConfig (via IO). 57 bool auto_detect; 58 GURL pac_url; 59 net::ProxyRulesExpectation proxy_rules; 60} tests[] = { 61 { // 0 62 TEST_DESC("No proxying"), 63 64 { // Input. 65 MK_MODE(DIRECT), // mode 66 }, 67 68 // Expected result. 69 false, // auto_detect 70 GURL(), // pac_url 71 net::ProxyRulesExpectation::Empty(), // proxy_rules 72 }, 73 74 { // 1 75 TEST_DESC("Auto detect"), 76 77 { // Input. 78 MK_MODE(AUTO_DETECT), // mode 79 }, 80 81 // Expected result. 82 true, // auto_detect 83 GURL(), // pac_url 84 net::ProxyRulesExpectation::Empty(), // proxy_rules 85 }, 86 87 { // 2 88 TEST_DESC("Valid PAC URL"), 89 90 { // Input. 91 MK_MODE(PAC_SCRIPT), // mode 92 "http://wpad/wpad.dat", // pac_url 93 }, 94 95 // Expected result. 96 false, // auto_detect 97 GURL("http://wpad/wpad.dat"), // pac_url 98 net::ProxyRulesExpectation::Empty(), // proxy_rules 99 }, 100 101 { // 3 102 TEST_DESC("Invalid PAC URL"), 103 104 { // Input. 105 MK_MODE(PAC_SCRIPT), // mode 106 "wpad.dat", // pac_url 107 }, 108 109 // Expected result. 110 false, // auto_detect 111 GURL(), // pac_url 112 net::ProxyRulesExpectation::Empty(), // proxy_rules 113 }, 114 115 { // 4 116 TEST_DESC("Single-host in proxy list"), 117 118 { // Input. 119 MK_MODE(SINGLE_PROXY), // mode 120 "", // pac_url 121 "www.google.com", // server 122 }, 123 124 // Expected result. 125 false, // auto_detect 126 GURL(), // pac_url 127 net::ProxyRulesExpectation::Single( // proxy_rules 128 "www.google.com:80", // single proxy 129 "<local>"), // bypass rules 130 }, 131 132 { // 5 133 TEST_DESC("Single-host, different port"), 134 135 { // Input. 136 MK_MODE(SINGLE_PROXY), // mode 137 "", // pac_url 138 "www.google.com:99", // server 139 }, 140 141 // Expected result. 142 false, // auto_detect 143 GURL(), // pac_url 144 net::ProxyRulesExpectation::Single( // proxy_rules 145 "www.google.com:99", // single 146 "<local>"), // bypass rules 147 }, 148 149 { // 6 150 TEST_DESC("Tolerate a scheme"), 151 152 { // Input. 153 MK_MODE(SINGLE_PROXY), // mode 154 "", // pac_url 155 "http://www.google.com:99", // server 156 }, 157 158 // Expected result. 159 false, // auto_detect 160 GURL(), // pac_url 161 net::ProxyRulesExpectation::Single( // proxy_rules 162 "www.google.com:99", // single proxy 163 "<local>"), // bypass rules 164 }, 165 166 { // 7 167 TEST_DESC("Per-scheme proxy rules"), 168 169 { // Input. 170 MK_MODE(PROXY_PER_SCHEME), // mode 171 "", // pac_url 172 "http=www.google.com:80;https=https://www.foo.com:110;" 173 "ftp=ftp.foo.com:121;socks=socks5://socks.com:888", // server 174 }, 175 176 // Expected result. 177 false, // auto_detect 178 GURL(), // pac_url 179 net::ProxyRulesExpectation::PerSchemeWithSocks( // proxy_rules 180 "www.google.com:80", // http 181 "https://www.foo.com:110", // https 182 "ftp.foo.com:121", // ftp 183 "socks5://socks.com:888", // fallback proxy 184 "<local>"), // bypass rules 185 }, 186 187 { // 8 188 TEST_DESC("Bypass rules"), 189 190 { // Input. 191 MK_MODE(SINGLE_PROXY), // mode 192 "", // pac_url 193 "www.google.com", // server 194 "*.google.com, *foo.com:99, 1.2.3.4:22, 127.0.0.1/8", // bypass_rules 195 }, 196 197 // Expected result. 198 false, // auto_detect 199 GURL(), // pac_url 200 net::ProxyRulesExpectation::Single( // proxy_rules 201 "www.google.com:80", // single proxy 202 // bypass_rules 203 "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8,<local>"), 204 }, 205}; // tests 206 207const char* kUserProfilePath = "user_profile"; 208 209} // namespace 210 211class ProxyConfigServiceImplTest : public testing::Test { 212 protected: 213 ProxyConfigServiceImplTest() 214 : ui_thread_(BrowserThread::UI, &loop_), 215 io_thread_(BrowserThread::IO, &loop_) {} 216 217 virtual void SetUp() { 218 DBusThreadManager::InitializeWithStub(); 219 NetworkHandler::Initialize(); 220 221 SetUpNetwork(); 222 223 PrefProxyConfigTrackerImpl::RegisterPrefs(pref_service_.registry()); 224 ProxyConfigServiceImpl::RegisterPrefs(pref_service_.registry()); 225 proxy_config_service_.reset(new ChromeProxyConfigService(NULL)); 226 config_service_impl_.reset(new ProxyConfigServiceImpl(&pref_service_)); 227 config_service_impl_->SetChromeProxyConfigService( 228 proxy_config_service_.get()); 229 // SetChromeProxyConfigService triggers update of initial prefs proxy 230 // config by tracker to chrome proxy config service, so flush all pending 231 // tasks so that tests start fresh. 232 loop_.RunUntilIdle(); 233 } 234 235 void SetUpNetwork() { 236 ShillProfileClient::TestInterface* profile_test = 237 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface(); 238 ShillServiceClient::TestInterface* service_test = 239 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 240 241 service_test->ClearServices(); 242 243 // Sends a notification about the added profile. 244 profile_test->AddProfile(kUserProfilePath, "user_hash"); 245 246 service_test->AddService("stub_wifi2", "wifi2_PSK", 247 flimflam::kTypeWifi, flimflam::kStateOnline, 248 true /* add to watchlist */); 249 service_test->SetServiceProperty("stub_wifi2", 250 flimflam::kGuidProperty, 251 base::StringValue("stub_wifi2")); 252 service_test->SetServiceProperty("stub_wifi2", 253 flimflam::kProfileProperty, 254 base::StringValue(kUserProfilePath)); 255 profile_test->AddService("stub_wifi2"); 256 257 loop_.RunUntilIdle(); 258 } 259 260 virtual void TearDown() { 261 config_service_impl_->DetachFromPrefService(); 262 loop_.RunUntilIdle(); 263 config_service_impl_.reset(); 264 proxy_config_service_.reset(); 265 NetworkHandler::Shutdown(); 266 DBusThreadManager::Shutdown(); 267 } 268 269 void InitConfigWithTestInput(const Input& input, 270 base::DictionaryValue* result) { 271 base::DictionaryValue* new_config = NULL; 272 switch (input.mode) { 273 case MK_MODE(DIRECT): 274 new_config = ProxyConfigDictionary::CreateDirect(); 275 break; 276 case MK_MODE(AUTO_DETECT): 277 new_config = ProxyConfigDictionary::CreateAutoDetect(); 278 break; 279 case MK_MODE(PAC_SCRIPT): 280 new_config = 281 ProxyConfigDictionary::CreatePacScript(input.pac_url, false); 282 break; 283 case MK_MODE(SINGLE_PROXY): 284 case MK_MODE(PROXY_PER_SCHEME): 285 new_config = 286 ProxyConfigDictionary::CreateFixedServers(input.server, 287 input.bypass_rules); 288 break; 289 } 290 result->Swap(new_config); 291 delete new_config; 292 } 293 294 void SetConfig(base::DictionaryValue* pref_proxy_config_dict) { 295 std::string proxy_config; 296 if (pref_proxy_config_dict) 297 base::JSONWriter::Write(pref_proxy_config_dict, &proxy_config); 298 299 NetworkStateHandler* network_state_handler = 300 NetworkHandler::Get()->network_state_handler(); 301 const NetworkState* network = network_state_handler->DefaultNetwork(); 302 ASSERT_TRUE(network); 303 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()-> 304 SetServiceProperty(network->path(), 305 flimflam::kProxyConfigProperty, 306 StringValue(proxy_config)); 307 } 308 309 // Synchronously gets the latest proxy config. 310 void SyncGetLatestProxyConfig(net::ProxyConfig* config) { 311 *config = net::ProxyConfig(); 312 // Let message loop process all messages. This will run 313 // ChromeProxyConfigService::UpdateProxyConfig, which is posted on IO from 314 // PrefProxyConfigTrackerImpl::OnProxyConfigChanged. 315 loop_.RunUntilIdle(); 316 net::ProxyConfigService::ConfigAvailability availability = 317 proxy_config_service_->GetLatestProxyConfig(config); 318 319 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, availability); 320 } 321 322 base::MessageLoop loop_; 323 scoped_ptr<ChromeProxyConfigService> proxy_config_service_; 324 scoped_ptr<ProxyConfigServiceImpl> config_service_impl_; 325 TestingPrefServiceSimple pref_service_; 326 327 private: 328 ScopedTestDeviceSettingsService test_device_settings_service_; 329 ScopedTestCrosSettings test_cros_settings_; 330 content::TestBrowserThread ui_thread_; 331 content::TestBrowserThread io_thread_; 332}; 333 334TEST_F(ProxyConfigServiceImplTest, NetworkProxy) { 335 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 336 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i, 337 tests[i].description.c_str())); 338 339 base::DictionaryValue test_config; 340 InitConfigWithTestInput(tests[i].input, &test_config); 341 SetConfig(&test_config); 342 343 net::ProxyConfig config; 344 SyncGetLatestProxyConfig(&config); 345 346 EXPECT_EQ(tests[i].auto_detect, config.auto_detect()); 347 EXPECT_EQ(tests[i].pac_url, config.pac_url()); 348 EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules())); 349 } 350} 351 352TEST_F(ProxyConfigServiceImplTest, DynamicPrefsOverride) { 353 // Groupings of 3 test inputs to use for managed, recommended and network 354 // proxies respectively. Only valid and non-direct test inputs are used. 355 const size_t proxies[][3] = { 356 { 1, 2, 4, }, 357 { 1, 4, 2, }, 358 { 4, 2, 1, }, 359 { 2, 1, 4, }, 360 { 2, 4, 5, }, 361 { 2, 5, 4, }, 362 { 5, 4, 2, }, 363 { 4, 2, 5, }, 364 { 4, 5, 6, }, 365 { 4, 6, 5, }, 366 { 6, 5, 4, }, 367 { 5, 4, 6, }, 368 { 5, 6, 7, }, 369 { 5, 7, 6, }, 370 { 7, 6, 5, }, 371 { 6, 5, 7, }, 372 { 6, 7, 8, }, 373 { 6, 8, 7, }, 374 { 8, 7, 6, }, 375 { 7, 6, 8, }, 376 }; 377 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(proxies); ++i) { 378 const TestParams& managed_params = tests[proxies[i][0]]; 379 const TestParams& recommended_params = tests[proxies[i][1]]; 380 const TestParams& network_params = tests[proxies[i][2]]; 381 382 SCOPED_TRACE(base::StringPrintf( 383 "Test[%" PRIuS "] managed=[%s], recommended=[%s], network=[%s]", i, 384 managed_params.description.c_str(), 385 recommended_params.description.c_str(), 386 network_params.description.c_str())); 387 388 base::DictionaryValue managed_config; 389 InitConfigWithTestInput(managed_params.input, &managed_config); 390 base::DictionaryValue recommended_config; 391 InitConfigWithTestInput(recommended_params.input, &recommended_config); 392 base::DictionaryValue network_config; 393 InitConfigWithTestInput(network_params.input, &network_config); 394 395 // Managed proxy pref should take effect over recommended proxy and 396 // non-existent network proxy. 397 SetConfig(NULL); 398 pref_service_.SetManagedPref(prefs::kProxy, managed_config.DeepCopy()); 399 pref_service_.SetRecommendedPref(prefs::kProxy, 400 recommended_config.DeepCopy()); 401 net::ProxyConfig actual_config; 402 SyncGetLatestProxyConfig(&actual_config); 403 EXPECT_EQ(managed_params.auto_detect, actual_config.auto_detect()); 404 EXPECT_EQ(managed_params.pac_url, actual_config.pac_url()); 405 EXPECT_TRUE(managed_params.proxy_rules.Matches( 406 actual_config.proxy_rules())); 407 408 // Recommended proxy pref should take effect when managed proxy pref is 409 // removed. 410 pref_service_.RemoveManagedPref(prefs::kProxy); 411 SyncGetLatestProxyConfig(&actual_config); 412 EXPECT_EQ(recommended_params.auto_detect, actual_config.auto_detect()); 413 EXPECT_EQ(recommended_params.pac_url, actual_config.pac_url()); 414 EXPECT_TRUE(recommended_params.proxy_rules.Matches( 415 actual_config.proxy_rules())); 416 417 // Network proxy should take take effect over recommended proxy pref. 418 SetConfig(&network_config); 419 SyncGetLatestProxyConfig(&actual_config); 420 EXPECT_EQ(network_params.auto_detect, actual_config.auto_detect()); 421 EXPECT_EQ(network_params.pac_url, actual_config.pac_url()); 422 EXPECT_TRUE(network_params.proxy_rules.Matches( 423 actual_config.proxy_rules())); 424 425 // Managed proxy pref should take effect over network proxy. 426 pref_service_.SetManagedPref(prefs::kProxy, managed_config.DeepCopy()); 427 SyncGetLatestProxyConfig(&actual_config); 428 EXPECT_EQ(managed_params.auto_detect, actual_config.auto_detect()); 429 EXPECT_EQ(managed_params.pac_url, actual_config.pac_url()); 430 EXPECT_TRUE(managed_params.proxy_rules.Matches( 431 actual_config.proxy_rules())); 432 433 // Network proxy should take effect over recommended proxy pref when managed 434 // proxy pref is removed. 435 pref_service_.RemoveManagedPref(prefs::kProxy); 436 SyncGetLatestProxyConfig(&actual_config); 437 EXPECT_EQ(network_params.auto_detect, actual_config.auto_detect()); 438 EXPECT_EQ(network_params.pac_url, actual_config.pac_url()); 439 EXPECT_TRUE(network_params.proxy_rules.Matches( 440 actual_config.proxy_rules())); 441 442 // Removing recommended proxy pref should have no effect on network proxy. 443 pref_service_.RemoveRecommendedPref(prefs::kProxy); 444 SyncGetLatestProxyConfig(&actual_config); 445 EXPECT_EQ(network_params.auto_detect, actual_config.auto_detect()); 446 EXPECT_EQ(network_params.pac_url, actual_config.pac_url()); 447 EXPECT_TRUE(network_params.proxy_rules.Matches( 448 actual_config.proxy_rules())); 449 } 450} 451 452} // namespace chromeos 453