proxy_config_service_linux_unittest.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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 "net/proxy/proxy_config_service_linux.h"
6
7#include <map>
8#include <string>
9#include <vector>
10
11#include "base/bind.h"
12#include "base/compiler_specific.h"
13#include "base/file_util.h"
14#include "base/files/file_path.h"
15#include "base/format_macros.h"
16#include "base/logging.h"
17#include "base/strings/string_util.h"
18#include "base/strings/stringprintf.h"
19#include "base/synchronization/waitable_event.h"
20#include "base/threading/thread.h"
21#include "net/proxy/proxy_config.h"
22#include "net/proxy/proxy_config_service_common_unittest.h"
23#include "testing/gtest/include/gtest/gtest.h"
24#include "testing/platform_test.h"
25
26namespace net {
27namespace {
28
29// Set of values for all environment variables that we might
30// query. NULL represents an unset variable.
31struct EnvVarValues {
32  // The strange capitalization is so that the field matches the
33  // environment variable name exactly.
34  const char *DESKTOP_SESSION, *HOME,
35      *KDEHOME, *KDE_SESSION_VERSION,
36      *auto_proxy, *all_proxy,
37      *http_proxy, *https_proxy, *ftp_proxy,
38      *SOCKS_SERVER, *SOCKS_VERSION,
39      *no_proxy;
40};
41
42// Undo macro pollution from GDK includes (from message_loop.h).
43#undef TRUE
44#undef FALSE
45
46// So as to distinguish between an unset gconf boolean variable and
47// one that is false.
48enum BoolSettingValue {
49  UNSET = 0, TRUE, FALSE
50};
51
52// Set of values for all gconf settings that we might query.
53struct GConfValues {
54  // strings
55  const char *mode, *autoconfig_url,
56      *http_host, *secure_host, *ftp_host, *socks_host;
57  // integers
58  int http_port, secure_port, ftp_port, socks_port;
59  // booleans
60  BoolSettingValue use_proxy, same_proxy, use_auth;
61  // string list
62  std::vector<std::string> ignore_hosts;
63};
64
65// Mapping from a setting name to the location of the corresponding
66// value (inside a EnvVarValues or GConfValues struct).
67template<typename key_type, typename value_type>
68struct SettingsTable {
69  typedef std::map<key_type, value_type*> map_type;
70
71  // Gets the value from its location
72  value_type Get(key_type key) {
73    typename map_type::const_iterator it = settings.find(key);
74    // In case there's a typo or the unittest becomes out of sync.
75    CHECK(it != settings.end()) << "key " << key << " not found";
76    value_type* value_ptr = it->second;
77    return *value_ptr;
78  }
79
80  map_type settings;
81};
82
83class MockEnvironment : public base::Environment {
84 public:
85  MockEnvironment() {
86#define ENTRY(x) table[#x] = &values.x
87    ENTRY(DESKTOP_SESSION);
88    ENTRY(HOME);
89    ENTRY(KDEHOME);
90    ENTRY(KDE_SESSION_VERSION);
91    ENTRY(auto_proxy);
92    ENTRY(all_proxy);
93    ENTRY(http_proxy);
94    ENTRY(https_proxy);
95    ENTRY(ftp_proxy);
96    ENTRY(no_proxy);
97    ENTRY(SOCKS_SERVER);
98    ENTRY(SOCKS_VERSION);
99#undef ENTRY
100    Reset();
101  }
102
103  // Zeroes all environment values.
104  void Reset() {
105    EnvVarValues zero_values = { 0 };
106    values = zero_values;
107  }
108
109  // Begin base::Environment implementation.
110  virtual bool GetVar(const char* variable_name, std::string* result) OVERRIDE {
111    std::map<std::string, const char**>::iterator it =
112        table.find(variable_name);
113    if (it != table.end() && *(it->second) != NULL) {
114      // Note that the variable may be defined but empty.
115      *result = *(it->second);
116      return true;
117    }
118    return false;
119  }
120
121  virtual bool SetVar(const char* variable_name, const std::string& new_value)
122      OVERRIDE {
123    ADD_FAILURE();
124    return false;
125  }
126
127  virtual bool UnSetVar(const char* variable_name) OVERRIDE {
128    ADD_FAILURE();
129    return false;
130  }
131  // End base::Environment implementation.
132
133  // Intentionally public, for convenience when setting up a test.
134  EnvVarValues values;
135
136 private:
137  std::map<std::string, const char**> table;
138};
139
140class MockSettingGetter
141    : public ProxyConfigServiceLinux::SettingGetter {
142 public:
143  typedef ProxyConfigServiceLinux::SettingGetter SettingGetter;
144  MockSettingGetter() {
145#define ENTRY(key, field) \
146      strings_table.settings[SettingGetter::key] = &values.field
147    ENTRY(PROXY_MODE, mode);
148    ENTRY(PROXY_AUTOCONF_URL, autoconfig_url);
149    ENTRY(PROXY_HTTP_HOST, http_host);
150    ENTRY(PROXY_HTTPS_HOST, secure_host);
151    ENTRY(PROXY_FTP_HOST, ftp_host);
152    ENTRY(PROXY_SOCKS_HOST, socks_host);
153#undef ENTRY
154#define ENTRY(key, field) \
155      ints_table.settings[SettingGetter::key] = &values.field
156    ENTRY(PROXY_HTTP_PORT, http_port);
157    ENTRY(PROXY_HTTPS_PORT, secure_port);
158    ENTRY(PROXY_FTP_PORT, ftp_port);
159    ENTRY(PROXY_SOCKS_PORT, socks_port);
160#undef ENTRY
161#define ENTRY(key, field) \
162      bools_table.settings[SettingGetter::key] = &values.field
163    ENTRY(PROXY_USE_HTTP_PROXY, use_proxy);
164    ENTRY(PROXY_USE_SAME_PROXY, same_proxy);
165    ENTRY(PROXY_USE_AUTHENTICATION, use_auth);
166#undef ENTRY
167    string_lists_table.settings[SettingGetter::PROXY_IGNORE_HOSTS] =
168        &values.ignore_hosts;
169    Reset();
170  }
171
172  // Zeros all environment values.
173  void Reset() {
174    GConfValues zero_values = { 0 };
175    values = zero_values;
176  }
177
178  virtual bool Init(base::SingleThreadTaskRunner* glib_thread_task_runner,
179                    base::MessageLoopForIO* file_loop) OVERRIDE {
180    return true;
181  }
182
183  virtual void ShutDown() OVERRIDE {}
184
185  virtual bool SetUpNotifications(ProxyConfigServiceLinux::Delegate* delegate)
186      OVERRIDE {
187    return true;
188  }
189
190  virtual base::SingleThreadTaskRunner* GetNotificationTaskRunner() OVERRIDE {
191    return NULL;
192  }
193
194  virtual ProxyConfigSource GetConfigSource() OVERRIDE {
195    return PROXY_CONFIG_SOURCE_TEST;
196  }
197
198  virtual bool GetString(StringSetting key, std::string* result) OVERRIDE {
199    const char* value = strings_table.Get(key);
200    if (value) {
201      *result = value;
202      return true;
203    }
204    return false;
205  }
206
207  virtual bool GetBool(BoolSetting key, bool* result) OVERRIDE {
208    BoolSettingValue value = bools_table.Get(key);
209    switch (value) {
210    case UNSET:
211      return false;
212    case TRUE:
213      *result = true;
214      break;
215    case FALSE:
216      *result = false;
217    }
218    return true;
219  }
220
221  virtual bool GetInt(IntSetting key, int* result) OVERRIDE {
222    // We don't bother to distinguish unset keys from 0 values.
223    *result = ints_table.Get(key);
224    return true;
225  }
226
227  virtual bool GetStringList(StringListSetting key,
228                             std::vector<std::string>* result) OVERRIDE {
229    *result = string_lists_table.Get(key);
230    // We don't bother to distinguish unset keys from empty lists.
231    return !result->empty();
232  }
233
234  virtual bool BypassListIsReversed() OVERRIDE {
235    return false;
236  }
237
238  virtual bool MatchHostsUsingSuffixMatching() OVERRIDE {
239    return false;
240  }
241
242  // Intentionally public, for convenience when setting up a test.
243  GConfValues values;
244
245 private:
246  SettingsTable<StringSetting, const char*> strings_table;
247  SettingsTable<BoolSetting, BoolSettingValue> bools_table;
248  SettingsTable<IntSetting, int> ints_table;
249  SettingsTable<StringListSetting,
250                std::vector<std::string> > string_lists_table;
251};
252
253}  // namespace
254}  // namespace net
255
256// This helper class runs ProxyConfigServiceLinux::GetLatestProxyConfig() on
257// the IO thread and synchronously waits for the result.
258// Some code duplicated from proxy_script_fetcher_unittest.cc.
259class SynchConfigGetter {
260 public:
261  // Takes ownership of |config_service|.
262  explicit SynchConfigGetter(net::ProxyConfigServiceLinux* config_service)
263      : event_(false, false),
264        io_thread_("IO_Thread"),
265        config_service_(config_service) {
266    // Start an IO thread.
267    base::Thread::Options options;
268    options.message_loop_type = base::MessageLoop::TYPE_IO;
269    io_thread_.StartWithOptions(options);
270
271    // Make sure the thread started.
272    io_thread_.message_loop()->PostTask(FROM_HERE,
273        base::Bind(&SynchConfigGetter::Init, base::Unretained(this)));
274    Wait();
275  }
276
277  ~SynchConfigGetter() {
278    // Let the config service post a destroy message to the IO thread
279    // before cleaning up that thread.
280    delete config_service_;
281    // Clean up the IO thread.
282    io_thread_.message_loop()->PostTask(FROM_HERE,
283        base::Bind(&SynchConfigGetter::CleanUp, base::Unretained(this)));
284    Wait();
285  }
286
287  // Does gconf setup and initial fetch of the proxy config,
288  // all on the calling thread (meant to be the thread with the
289  // default glib main loop, which is the UI thread).
290  void SetupAndInitialFetch() {
291    base::MessageLoop* file_loop = io_thread_.message_loop();
292    DCHECK_EQ(base::MessageLoop::TYPE_IO, file_loop->type());
293    // We pass the mock IO thread as both the IO and file threads.
294    config_service_->SetupAndFetchInitialConfig(
295        base::MessageLoopProxy::current().get(),
296        io_thread_.message_loop_proxy().get(),
297        static_cast<base::MessageLoopForIO*>(file_loop));
298  }
299  // Synchronously gets the proxy config.
300  net::ProxyConfigService::ConfigAvailability SyncGetLatestProxyConfig(
301      net::ProxyConfig* config) {
302    io_thread_.message_loop()->PostTask(FROM_HERE,
303        base::Bind(&SynchConfigGetter::GetLatestConfigOnIOThread,
304                   base::Unretained(this)));
305    Wait();
306    *config = proxy_config_;
307    return get_latest_config_result_;
308  }
309
310 private:
311  // [Runs on |io_thread_|]
312  void Init() {
313    event_.Signal();
314  }
315
316  // Calls GetLatestProxyConfig, running on |io_thread_| Signals |event_|
317  // on completion.
318  void GetLatestConfigOnIOThread() {
319    get_latest_config_result_ =
320        config_service_->GetLatestProxyConfig(&proxy_config_);
321    event_.Signal();
322  }
323
324  // [Runs on |io_thread_|] Signals |event_| on cleanup completion.
325  void CleanUp() {
326    base::MessageLoop::current()->RunUntilIdle();
327    event_.Signal();
328  }
329
330  void Wait() {
331    event_.Wait();
332    event_.Reset();
333  }
334
335  base::WaitableEvent event_;
336  base::Thread io_thread_;
337
338  net::ProxyConfigServiceLinux* config_service_;
339
340  // The config obtained by |io_thread_| and read back by the main
341  // thread.
342  net::ProxyConfig proxy_config_;
343
344  // Return value from GetLatestProxyConfig().
345  net::ProxyConfigService::ConfigAvailability get_latest_config_result_;
346};
347
348namespace net {
349
350// This test fixture is only really needed for the KDEConfigParser test case,
351// but all the test cases with the same prefix ("ProxyConfigServiceLinuxTest")
352// must use the same test fixture class (also "ProxyConfigServiceLinuxTest").
353class ProxyConfigServiceLinuxTest : public PlatformTest {
354 protected:
355  virtual void SetUp() OVERRIDE {
356    PlatformTest::SetUp();
357    // Set up a temporary KDE home directory.
358    std::string prefix("ProxyConfigServiceLinuxTest_user_home");
359    base::CreateNewTempDirectory(prefix, &user_home_);
360    kde_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde"));
361    base::FilePath path = kde_home_.Append(FILE_PATH_LITERAL("share"));
362    path = path.Append(FILE_PATH_LITERAL("config"));
363    base::CreateDirectory(path);
364    kioslaverc_ = path.Append(FILE_PATH_LITERAL("kioslaverc"));
365    // Set up paths but do not create the directory for .kde4.
366    kde4_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde4"));
367    path = kde4_home_.Append(FILE_PATH_LITERAL("share"));
368    kde4_config_ = path.Append(FILE_PATH_LITERAL("config"));
369    kioslaverc4_ = kde4_config_.Append(FILE_PATH_LITERAL("kioslaverc"));
370  }
371
372  virtual void TearDown() OVERRIDE {
373    // Delete the temporary KDE home directory.
374    base::DeleteFile(user_home_, true);
375    PlatformTest::TearDown();
376  }
377
378  base::FilePath user_home_;
379  // KDE3 paths.
380  base::FilePath kde_home_;
381  base::FilePath kioslaverc_;
382  // KDE4 paths.
383  base::FilePath kde4_home_;
384  base::FilePath kde4_config_;
385  base::FilePath kioslaverc4_;
386};
387
388// Builds an identifier for each test in an array.
389#define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc)
390
391TEST_F(ProxyConfigServiceLinuxTest, BasicGConfTest) {
392  std::vector<std::string> empty_ignores;
393
394  std::vector<std::string> google_ignores;
395  google_ignores.push_back("*.google.com");
396
397  // Inspired from proxy_config_service_win_unittest.cc.
398  // Very neat, but harder to track down failures though.
399  const struct {
400    // Short description to identify the test
401    std::string description;
402
403    // Input.
404    GConfValues values;
405
406    // Expected outputs (availability and fields of ProxyConfig).
407    ProxyConfigService::ConfigAvailability availability;
408    bool auto_detect;
409    GURL pac_url;
410    ProxyRulesExpectation proxy_rules;
411  } tests[] = {
412    {
413      TEST_DESC("No proxying"),
414      { // Input.
415        "none",                   // mode
416        "",                       // autoconfig_url
417        "", "", "", "",           // hosts
418        0, 0, 0, 0,               // ports
419        FALSE, FALSE, FALSE,      // use, same, auth
420        empty_ignores,            // ignore_hosts
421      },
422
423      // Expected result.
424      ProxyConfigService::CONFIG_VALID,
425      false,                      // auto_detect
426      GURL(),                     // pac_url
427      ProxyRulesExpectation::Empty(),
428    },
429
430    {
431      TEST_DESC("Auto detect"),
432      { // Input.
433        "auto",                   // mode
434        "",                       // autoconfig_url
435        "", "", "", "",           // hosts
436        0, 0, 0, 0,               // ports
437        FALSE, FALSE, FALSE,      // use, same, auth
438        empty_ignores,            // ignore_hosts
439      },
440
441      // Expected result.
442      ProxyConfigService::CONFIG_VALID,
443      true,                       // auto_detect
444      GURL(),                     // pac_url
445      ProxyRulesExpectation::Empty(),
446    },
447
448    {
449      TEST_DESC("Valid PAC URL"),
450      { // Input.
451        "auto",                      // mode
452        "http://wpad/wpad.dat",      // autoconfig_url
453        "", "", "", "",              // hosts
454        0, 0, 0, 0,                  // ports
455        FALSE, FALSE, FALSE,         // use, same, auth
456        empty_ignores,               // ignore_hosts
457      },
458
459      // Expected result.
460      ProxyConfigService::CONFIG_VALID,
461      false,                         // auto_detect
462      GURL("http://wpad/wpad.dat"),  // pac_url
463      ProxyRulesExpectation::Empty(),
464    },
465
466    {
467      TEST_DESC("Invalid PAC URL"),
468      { // Input.
469        "auto",                      // mode
470        "wpad.dat",                  // autoconfig_url
471        "", "", "", "",              // hosts
472        0, 0, 0, 0,                  // ports
473        FALSE, FALSE, FALSE,         // use, same, auth
474        empty_ignores,               // ignore_hosts
475      },
476
477      // Expected result.
478      ProxyConfigService::CONFIG_VALID,
479      false,                          // auto_detect
480      GURL(),                        // pac_url
481      ProxyRulesExpectation::Empty(),
482    },
483
484    {
485      TEST_DESC("Single-host in proxy list"),
486      { // Input.
487        "manual",                              // mode
488        "",                                    // autoconfig_url
489        "www.google.com", "", "", "",          // hosts
490        80, 0, 0, 0,                           // ports
491        TRUE, TRUE, FALSE,                     // use, same, auth
492        empty_ignores,                         // ignore_hosts
493      },
494
495      // Expected result.
496      ProxyConfigService::CONFIG_VALID,
497      false,                                   // auto_detect
498      GURL(),                                  // pac_url
499      ProxyRulesExpectation::Single(
500          "www.google.com:80",  // single proxy
501          ""),                  // bypass rules
502    },
503
504    {
505      TEST_DESC("use_http_proxy is honored"),
506      { // Input.
507        "manual",                              // mode
508        "",                                    // autoconfig_url
509        "www.google.com", "", "", "",          // hosts
510        80, 0, 0, 0,                           // ports
511        FALSE, TRUE, FALSE,                    // use, same, auth
512        empty_ignores,                         // ignore_hosts
513      },
514
515      // Expected result.
516      ProxyConfigService::CONFIG_VALID,
517      false,                                   // auto_detect
518      GURL(),                                  // pac_url
519      ProxyRulesExpectation::Empty(),
520    },
521
522    {
523      TEST_DESC("use_http_proxy and use_same_proxy are optional"),
524      { // Input.
525        "manual",                                     // mode
526        "",                                           // autoconfig_url
527        "www.google.com", "", "", "",                 // hosts
528        80, 0, 0, 0,                                  // ports
529        UNSET, UNSET, FALSE,                          // use, same, auth
530        empty_ignores,                                // ignore_hosts
531      },
532
533      // Expected result.
534      ProxyConfigService::CONFIG_VALID,
535      false,                                          // auto_detect
536      GURL(),                                         // pac_url
537      ProxyRulesExpectation::PerScheme(
538          "www.google.com:80",  // http
539          "",                   // https
540          "",                   // ftp
541          ""),                  // bypass rules
542    },
543
544    {
545      TEST_DESC("Single-host, different port"),
546      { // Input.
547        "manual",                                     // mode
548        "",                                           // autoconfig_url
549        "www.google.com", "", "", "",                 // hosts
550        88, 0, 0, 0,                                  // ports
551        TRUE, TRUE, FALSE,                            // use, same, auth
552        empty_ignores,                                // ignore_hosts
553      },
554
555      // Expected result.
556      ProxyConfigService::CONFIG_VALID,
557      false,                                          // auto_detect
558      GURL(),                                         // pac_url
559      ProxyRulesExpectation::Single(
560          "www.google.com:88",  // single proxy
561          ""),                  // bypass rules
562    },
563
564    {
565      TEST_DESC("Per-scheme proxy rules"),
566      { // Input.
567        "manual",                                     // mode
568        "",                                           // autoconfig_url
569        "www.google.com",                             // http_host
570        "www.foo.com",                                // secure_host
571        "ftp.foo.com",                                // ftp
572        "",                                           // socks
573        88, 110, 121, 0,                              // ports
574        TRUE, FALSE, FALSE,                           // use, same, auth
575        empty_ignores,                                // ignore_hosts
576      },
577
578      // Expected result.
579      ProxyConfigService::CONFIG_VALID,
580      false,                                          // auto_detect
581      GURL(),                                         // pac_url
582      ProxyRulesExpectation::PerScheme(
583          "www.google.com:88",  // http
584          "www.foo.com:110",    // https
585          "ftp.foo.com:121",    // ftp
586          ""),                  // bypass rules
587    },
588
589    {
590      TEST_DESC("socks"),
591      { // Input.
592        "manual",                                     // mode
593        "",                                           // autoconfig_url
594        "", "", "", "socks.com",                      // hosts
595        0, 0, 0, 99,                                  // ports
596        TRUE, FALSE, FALSE,                           // use, same, auth
597        empty_ignores,                                // ignore_hosts
598      },
599
600      // Expected result.
601      ProxyConfigService::CONFIG_VALID,
602      false,                                          // auto_detect
603      GURL(),                                         // pac_url
604      ProxyRulesExpectation::Single(
605          "socks5://socks.com:99",  // single proxy
606          "")                       // bypass rules
607    },
608
609    {
610      TEST_DESC("Per-scheme proxy rules with fallback to SOCKS"),
611      { // Input.
612        "manual",                                     // mode
613        "",                                           // autoconfig_url
614        "www.google.com",                             // http_host
615        "www.foo.com",                                // secure_host
616        "ftp.foo.com",                                // ftp
617        "foobar.net",                                 // socks
618        88, 110, 121, 99,                             // ports
619        TRUE, FALSE, FALSE,                           // use, same, auth
620        empty_ignores,                                // ignore_hosts
621      },
622
623      // Expected result.
624      ProxyConfigService::CONFIG_VALID,
625      false,                                          // auto_detect
626      GURL(),                                         // pac_url
627      ProxyRulesExpectation::PerSchemeWithSocks(
628          "www.google.com:88",      // http
629          "www.foo.com:110",        // https
630          "ftp.foo.com:121",        // ftp
631          "socks5://foobar.net:99", // socks
632          ""),                      // bypass rules
633    },
634
635    {
636      TEST_DESC("Per-scheme proxy rules (just HTTP) with fallback to SOCKS"),
637      { // Input.
638        "manual",                                     // mode
639        "",                                           // autoconfig_url
640        "www.google.com",                             // http_host
641        "",                                           // secure_host
642        "",                                           // ftp
643        "foobar.net",                                 // socks
644        88, 0, 0, 99,                                 // ports
645        TRUE, FALSE, FALSE,                           // use, same, auth
646        empty_ignores,                                // ignore_hosts
647      },
648
649      // Expected result.
650      ProxyConfigService::CONFIG_VALID,
651      false,                                          // auto_detect
652      GURL(),                                         // pac_url
653      ProxyRulesExpectation::PerSchemeWithSocks(
654          "www.google.com:88",      // http
655          "",                       // https
656          "",                       // ftp
657          "socks5://foobar.net:99", // socks
658          ""),                      // bypass rules
659    },
660
661    {
662      TEST_DESC("Bypass *.google.com"),
663      { // Input.
664        "manual",                                     // mode
665        "",                                           // autoconfig_url
666        "www.google.com", "", "", "",                 // hosts
667        80, 0, 0, 0,                                  // ports
668        TRUE, TRUE, FALSE,                            // use, same, auth
669        google_ignores,                               // ignore_hosts
670      },
671
672      ProxyConfigService::CONFIG_VALID,
673      false,                                          // auto_detect
674      GURL(),                                         // pac_url
675      ProxyRulesExpectation::Single(
676          "www.google.com:80",   // single proxy
677          "*.google.com"),       // bypass rules
678    },
679  };
680
681  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
682    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
683                                    tests[i].description.c_str()));
684    MockEnvironment* env = new MockEnvironment;
685    MockSettingGetter* setting_getter = new MockSettingGetter;
686    SynchConfigGetter sync_config_getter(
687        new ProxyConfigServiceLinux(env, setting_getter));
688    ProxyConfig config;
689    setting_getter->values = tests[i].values;
690    sync_config_getter.SetupAndInitialFetch();
691    ProxyConfigService::ConfigAvailability availability =
692        sync_config_getter.SyncGetLatestProxyConfig(&config);
693    EXPECT_EQ(tests[i].availability, availability);
694
695    if (availability == ProxyConfigService::CONFIG_VALID) {
696      EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
697      EXPECT_EQ(tests[i].pac_url, config.pac_url());
698      EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
699    }
700  }
701}
702
703TEST_F(ProxyConfigServiceLinuxTest, BasicEnvTest) {
704  // Inspired from proxy_config_service_win_unittest.cc.
705  const struct {
706    // Short description to identify the test
707    std::string description;
708
709    // Input.
710    EnvVarValues values;
711
712    // Expected outputs (availability and fields of ProxyConfig).
713    ProxyConfigService::ConfigAvailability availability;
714    bool auto_detect;
715    GURL pac_url;
716    ProxyRulesExpectation proxy_rules;
717  } tests[] = {
718    {
719      TEST_DESC("No proxying"),
720      { // Input.
721        NULL,  // DESKTOP_SESSION
722        NULL,  // HOME
723        NULL,  // KDEHOME
724        NULL,  // KDE_SESSION_VERSION
725        NULL,  // auto_proxy
726        NULL,  // all_proxy
727        NULL, NULL, NULL,  // per-proto proxies
728        NULL, NULL,  // SOCKS
729        "*",  // no_proxy
730      },
731
732      // Expected result.
733      ProxyConfigService::CONFIG_VALID,
734      false,                      // auto_detect
735      GURL(),                     // pac_url
736      ProxyRulesExpectation::Empty(),
737    },
738
739    {
740      TEST_DESC("Auto detect"),
741      { // Input.
742        NULL,  // DESKTOP_SESSION
743        NULL,  // HOME
744        NULL,  // KDEHOME
745        NULL,  // KDE_SESSION_VERSION
746        "",    // auto_proxy
747        NULL,  // all_proxy
748        NULL, NULL, NULL,  // per-proto proxies
749        NULL, NULL,  // SOCKS
750        NULL,  // no_proxy
751      },
752
753      // Expected result.
754      ProxyConfigService::CONFIG_VALID,
755      true,                       // auto_detect
756      GURL(),                     // pac_url
757      ProxyRulesExpectation::Empty(),
758    },
759
760    {
761      TEST_DESC("Valid PAC URL"),
762      { // Input.
763        NULL,  // DESKTOP_SESSION
764        NULL,  // HOME
765        NULL,  // KDEHOME
766        NULL,  // KDE_SESSION_VERSION
767        "http://wpad/wpad.dat",  // auto_proxy
768        NULL,  // all_proxy
769        NULL, NULL, NULL,  // per-proto proxies
770        NULL, NULL,  // SOCKS
771        NULL,  // no_proxy
772      },
773
774      // Expected result.
775      ProxyConfigService::CONFIG_VALID,
776      false,                         // auto_detect
777      GURL("http://wpad/wpad.dat"),  // pac_url
778      ProxyRulesExpectation::Empty(),
779    },
780
781    {
782      TEST_DESC("Invalid PAC URL"),
783      { // Input.
784        NULL,  // DESKTOP_SESSION
785        NULL,  // HOME
786        NULL,  // KDEHOME
787        NULL,  // KDE_SESSION_VERSION
788        "wpad.dat",  // auto_proxy
789        NULL,  // all_proxy
790        NULL, NULL, NULL,  // per-proto proxies
791        NULL, NULL,  // SOCKS
792        NULL,  // no_proxy
793      },
794
795      // Expected result.
796      ProxyConfigService::CONFIG_VALID,
797      false,                       // auto_detect
798      GURL(),                     // pac_url
799      ProxyRulesExpectation::Empty(),
800    },
801
802    {
803      TEST_DESC("Single-host in proxy list"),
804      { // Input.
805        NULL,  // DESKTOP_SESSION
806        NULL,  // HOME
807        NULL,  // KDEHOME
808        NULL,  // KDE_SESSION_VERSION
809        NULL,  // auto_proxy
810        "www.google.com",  // all_proxy
811        NULL, NULL, NULL,  // per-proto proxies
812        NULL, NULL,  // SOCKS
813        NULL,  // no_proxy
814      },
815
816      // Expected result.
817      ProxyConfigService::CONFIG_VALID,
818      false,                                   // auto_detect
819      GURL(),                                  // pac_url
820      ProxyRulesExpectation::Single(
821          "www.google.com:80",  // single proxy
822          ""),                  // bypass rules
823    },
824
825    {
826      TEST_DESC("Single-host, different port"),
827      { // Input.
828        NULL,  // DESKTOP_SESSION
829        NULL,  // HOME
830        NULL,  // KDEHOME
831        NULL,  // KDE_SESSION_VERSION
832        NULL,  // auto_proxy
833        "www.google.com:99",  // all_proxy
834        NULL, NULL, NULL,  // per-proto proxies
835        NULL, NULL,  // SOCKS
836        NULL,  // no_proxy
837      },
838
839      // Expected result.
840      ProxyConfigService::CONFIG_VALID,
841      false,                                   // auto_detect
842      GURL(),                                  // pac_url
843      ProxyRulesExpectation::Single(
844          "www.google.com:99",  // single
845          ""),                  // bypass rules
846    },
847
848    {
849      TEST_DESC("Tolerate a scheme"),
850      { // Input.
851        NULL,  // DESKTOP_SESSION
852        NULL,  // HOME
853        NULL,  // KDEHOME
854        NULL,  // KDE_SESSION_VERSION
855        NULL,  // auto_proxy
856        "http://www.google.com:99",  // all_proxy
857        NULL, NULL, NULL,  // per-proto proxies
858        NULL, NULL,  // SOCKS
859        NULL,  // no_proxy
860      },
861
862      // Expected result.
863      ProxyConfigService::CONFIG_VALID,
864      false,                                   // auto_detect
865      GURL(),                                  // pac_url
866      ProxyRulesExpectation::Single(
867          "www.google.com:99",  // single proxy
868          ""),                  // bypass rules
869    },
870
871    {
872      TEST_DESC("Per-scheme proxy rules"),
873      { // Input.
874        NULL,  // DESKTOP_SESSION
875        NULL,  // HOME
876        NULL,  // KDEHOME
877        NULL,  // KDE_SESSION_VERSION
878        NULL,  // auto_proxy
879        NULL,  // all_proxy
880        "www.google.com:80", "www.foo.com:110", "ftp.foo.com:121",  // per-proto
881        NULL, NULL,  // SOCKS
882        NULL,  // no_proxy
883      },
884
885      // Expected result.
886      ProxyConfigService::CONFIG_VALID,
887      false,                                   // auto_detect
888      GURL(),                                  // pac_url
889      ProxyRulesExpectation::PerScheme(
890          "www.google.com:80",  // http
891          "www.foo.com:110",    // https
892          "ftp.foo.com:121",    // ftp
893          ""),                  // bypass rules
894    },
895
896    {
897      TEST_DESC("socks"),
898      { // Input.
899        NULL,  // DESKTOP_SESSION
900        NULL,  // HOME
901        NULL,  // KDEHOME
902        NULL,  // KDE_SESSION_VERSION
903        NULL,  // auto_proxy
904        "",  // all_proxy
905        NULL, NULL, NULL,  // per-proto proxies
906        "socks.com:888", NULL,  // SOCKS
907        NULL,  // no_proxy
908      },
909
910      // Expected result.
911      ProxyConfigService::CONFIG_VALID,
912      false,                                   // auto_detect
913      GURL(),                                  // pac_url
914      ProxyRulesExpectation::Single(
915          "socks5://socks.com:888",  // single proxy
916          ""),                       // bypass rules
917    },
918
919    {
920      TEST_DESC("socks4"),
921      { // Input.
922        NULL,  // DESKTOP_SESSION
923        NULL,  // HOME
924        NULL,  // KDEHOME
925        NULL,  // KDE_SESSION_VERSION
926        NULL,  // auto_proxy
927        "",  // all_proxy
928        NULL, NULL, NULL,  // per-proto proxies
929        "socks.com:888", "4",  // SOCKS
930        NULL,  // no_proxy
931      },
932
933      // Expected result.
934      ProxyConfigService::CONFIG_VALID,
935      false,                                   // auto_detect
936      GURL(),                                  // pac_url
937      ProxyRulesExpectation::Single(
938          "socks4://socks.com:888",  // single proxy
939          ""),                       // bypass rules
940    },
941
942    {
943      TEST_DESC("socks default port"),
944      { // Input.
945        NULL,  // DESKTOP_SESSION
946        NULL,  // HOME
947        NULL,  // KDEHOME
948        NULL,  // KDE_SESSION_VERSION
949        NULL,  // auto_proxy
950        "",  // all_proxy
951        NULL, NULL, NULL,  // per-proto proxies
952        "socks.com", NULL,  // SOCKS
953        NULL,  // no_proxy
954      },
955
956      // Expected result.
957      ProxyConfigService::CONFIG_VALID,
958      false,                                   // auto_detect
959      GURL(),                                  // pac_url
960      ProxyRulesExpectation::Single(
961          "socks5://socks.com:1080",  // single proxy
962          ""),                        // bypass rules
963    },
964
965    {
966      TEST_DESC("bypass"),
967      { // Input.
968        NULL,  // DESKTOP_SESSION
969        NULL,  // HOME
970        NULL,  // KDEHOME
971        NULL,  // KDE_SESSION_VERSION
972        NULL,  // auto_proxy
973        "www.google.com",  // all_proxy
974        NULL, NULL, NULL,  // per-proto
975        NULL, NULL,  // SOCKS
976        ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8",  // no_proxy
977      },
978
979      // Expected result.
980      ProxyConfigService::CONFIG_VALID,
981      false,                      // auto_detect
982      GURL(),                     // pac_url
983      ProxyRulesExpectation::Single(
984          "www.google.com:80",
985          "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"),
986    },
987  };
988
989  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
990    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
991                                    tests[i].description.c_str()));
992    MockEnvironment* env = new MockEnvironment;
993    MockSettingGetter* setting_getter = new MockSettingGetter;
994    SynchConfigGetter sync_config_getter(
995        new ProxyConfigServiceLinux(env, setting_getter));
996    ProxyConfig config;
997    env->values = tests[i].values;
998    sync_config_getter.SetupAndInitialFetch();
999    ProxyConfigService::ConfigAvailability availability =
1000        sync_config_getter.SyncGetLatestProxyConfig(&config);
1001    EXPECT_EQ(tests[i].availability, availability);
1002
1003    if (availability == ProxyConfigService::CONFIG_VALID) {
1004      EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
1005      EXPECT_EQ(tests[i].pac_url, config.pac_url());
1006      EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
1007    }
1008  }
1009}
1010
1011TEST_F(ProxyConfigServiceLinuxTest, GconfNotification) {
1012  MockEnvironment* env = new MockEnvironment;
1013  MockSettingGetter* setting_getter = new MockSettingGetter;
1014  ProxyConfigServiceLinux* service =
1015      new ProxyConfigServiceLinux(env, setting_getter);
1016  SynchConfigGetter sync_config_getter(service);
1017  ProxyConfig config;
1018
1019  // Start with no proxy.
1020  setting_getter->values.mode = "none";
1021  sync_config_getter.SetupAndInitialFetch();
1022  EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1023            sync_config_getter.SyncGetLatestProxyConfig(&config));
1024  EXPECT_FALSE(config.auto_detect());
1025
1026  // Now set to auto-detect.
1027  setting_getter->values.mode = "auto";
1028  // Simulate setting change notification callback.
1029  service->OnCheckProxyConfigSettings();
1030  EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1031            sync_config_getter.SyncGetLatestProxyConfig(&config));
1032  EXPECT_TRUE(config.auto_detect());
1033}
1034
1035TEST_F(ProxyConfigServiceLinuxTest, KDEConfigParser) {
1036  // One of the tests below needs a worst-case long line prefix. We build it
1037  // programmatically so that it will always be the right size.
1038  std::string long_line;
1039  size_t limit = ProxyConfigServiceLinux::SettingGetter::BUFFER_SIZE - 1;
1040  for (size_t i = 0; i < limit; ++i)
1041    long_line += "-";
1042
1043  // Inspired from proxy_config_service_win_unittest.cc.
1044  const struct {
1045    // Short description to identify the test
1046    std::string description;
1047
1048    // Input.
1049    std::string kioslaverc;
1050    EnvVarValues env_values;
1051
1052    // Expected outputs (availability and fields of ProxyConfig).
1053    ProxyConfigService::ConfigAvailability availability;
1054    bool auto_detect;
1055    GURL pac_url;
1056    ProxyRulesExpectation proxy_rules;
1057  } tests[] = {
1058    {
1059      TEST_DESC("No proxying"),
1060
1061      // Input.
1062      "[Proxy Settings]\nProxyType=0\n",
1063      {},                                      // env_values
1064
1065      // Expected result.
1066      ProxyConfigService::CONFIG_VALID,
1067      false,                      // auto_detect
1068      GURL(),                     // pac_url
1069      ProxyRulesExpectation::Empty(),
1070    },
1071
1072    {
1073      TEST_DESC("Auto detect"),
1074
1075      // Input.
1076      "[Proxy Settings]\nProxyType=3\n",
1077      {},                                      // env_values
1078
1079      // Expected result.
1080      ProxyConfigService::CONFIG_VALID,
1081      true,                       // auto_detect
1082      GURL(),                     // pac_url
1083      ProxyRulesExpectation::Empty(),
1084    },
1085
1086    {
1087      TEST_DESC("Valid PAC URL"),
1088
1089      // Input.
1090      "[Proxy Settings]\nProxyType=2\n"
1091          "Proxy Config Script=http://wpad/wpad.dat\n",
1092      {},                                      // env_values
1093
1094      // Expected result.
1095      ProxyConfigService::CONFIG_VALID,
1096      false,                         // auto_detect
1097      GURL("http://wpad/wpad.dat"),  // pac_url
1098      ProxyRulesExpectation::Empty(),
1099    },
1100
1101    {
1102      TEST_DESC("Valid PAC file without file://"),
1103
1104      // Input.
1105      "[Proxy Settings]\nProxyType=2\n"
1106          "Proxy Config Script=/wpad/wpad.dat\n",
1107      {},                                      // env_values
1108
1109      // Expected result.
1110      ProxyConfigService::CONFIG_VALID,
1111      false,                         // auto_detect
1112      GURL("file:///wpad/wpad.dat"),  // pac_url
1113      ProxyRulesExpectation::Empty(),
1114    },
1115
1116    {
1117      TEST_DESC("Per-scheme proxy rules"),
1118
1119      // Input.
1120      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1121          "httpsProxy=www.foo.com\nftpProxy=ftp.foo.com\n",
1122      {},                                      // env_values
1123
1124      // Expected result.
1125      ProxyConfigService::CONFIG_VALID,
1126      false,                                   // auto_detect
1127      GURL(),                                  // pac_url
1128      ProxyRulesExpectation::PerScheme(
1129          "www.google.com:80",  // http
1130          "www.foo.com:80",     // https
1131          "ftp.foo.com:80",     // http
1132          ""),                  // bypass rules
1133    },
1134
1135    {
1136      TEST_DESC("Only HTTP proxy specified"),
1137
1138      // Input.
1139      "[Proxy Settings]\nProxyType=1\n"
1140          "httpProxy=www.google.com\n",
1141      {},                                      // env_values
1142
1143      // Expected result.
1144      ProxyConfigService::CONFIG_VALID,
1145      false,                                   // auto_detect
1146      GURL(),                                  // pac_url
1147      ProxyRulesExpectation::PerScheme(
1148          "www.google.com:80",  // http
1149          "",                   // https
1150          "",                   // ftp
1151          ""),                  // bypass rules
1152    },
1153
1154    {
1155      TEST_DESC("Only HTTP proxy specified, different port"),
1156
1157      // Input.
1158      "[Proxy Settings]\nProxyType=1\n"
1159          "httpProxy=www.google.com:88\n",
1160      {},                                      // env_values
1161
1162      // Expected result.
1163      ProxyConfigService::CONFIG_VALID,
1164      false,                                   // auto_detect
1165      GURL(),                                  // pac_url
1166      ProxyRulesExpectation::PerScheme(
1167          "www.google.com:88",  // http
1168          "",                   // https
1169          "",                   // ftp
1170          ""),                  // bypass rules
1171    },
1172
1173    {
1174      TEST_DESC("Only HTTP proxy specified, different port, space-delimited"),
1175
1176      // Input.
1177      "[Proxy Settings]\nProxyType=1\n"
1178          "httpProxy=www.google.com 88\n",
1179      {},                                      // env_values
1180
1181      // Expected result.
1182      ProxyConfigService::CONFIG_VALID,
1183      false,                                   // auto_detect
1184      GURL(),                                  // pac_url
1185      ProxyRulesExpectation::PerScheme(
1186          "www.google.com:88",  // http
1187          "",                   // https
1188          "",                   // ftp
1189          ""),                  // bypass rules
1190    },
1191
1192    {
1193      TEST_DESC("Bypass *.google.com"),
1194
1195      // Input.
1196      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1197          "NoProxyFor=.google.com\n",
1198      {},                                      // env_values
1199
1200      // Expected result.
1201      ProxyConfigService::CONFIG_VALID,
1202      false,                                   // auto_detect
1203      GURL(),                                  // pac_url
1204      ProxyRulesExpectation::PerScheme(
1205          "www.google.com:80",  // http
1206          "",                   // https
1207          "",                   // ftp
1208          "*.google.com"),      // bypass rules
1209    },
1210
1211    {
1212      TEST_DESC("Bypass *.google.com and *.kde.org"),
1213
1214      // Input.
1215      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1216          "NoProxyFor=.google.com,.kde.org\n",
1217      {},                                      // env_values
1218
1219      // Expected result.
1220      ProxyConfigService::CONFIG_VALID,
1221      false,                                   // auto_detect
1222      GURL(),                                  // pac_url
1223      ProxyRulesExpectation::PerScheme(
1224          "www.google.com:80",           // http
1225          "",                            // https
1226          "",                            // ftp
1227          "*.google.com,*.kde.org"),     // bypass rules
1228    },
1229
1230    {
1231      TEST_DESC("Correctly parse bypass list with ReversedException"),
1232
1233      // Input.
1234      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1235          "NoProxyFor=.google.com\nReversedException=true\n",
1236      {},                                      // env_values
1237
1238      // Expected result.
1239      ProxyConfigService::CONFIG_VALID,
1240      false,                                   // auto_detect
1241      GURL(),                                  // pac_url
1242      ProxyRulesExpectation::PerSchemeWithBypassReversed(
1243          "www.google.com:80",  // http
1244          "",                   // https
1245          "",                   // ftp
1246          "*.google.com"),      // bypass rules
1247    },
1248
1249    {
1250      TEST_DESC("socks"),
1251
1252      // Input.
1253      "[Proxy Settings]\nProxyType=1\nsocksProxy=socks.com 888\n",
1254      {},                                      // env_values
1255
1256      // Expected result.
1257      ProxyConfigService::CONFIG_VALID,
1258      false,                                   // auto_detect
1259      GURL(),                                  // pac_url
1260      ProxyRulesExpectation::Single(
1261          "socks5://socks.com:888",  // single proxy
1262          ""),                       // bypass rules
1263    },
1264
1265    {
1266      TEST_DESC("socks4"),
1267
1268      // Input.
1269      "[Proxy Settings]\nProxyType=1\nsocksProxy=socks4://socks.com 888\n",
1270      {},                                      // env_values
1271
1272      // Expected result.
1273      ProxyConfigService::CONFIG_VALID,
1274      false,                                   // auto_detect
1275      GURL(),                                  // pac_url
1276      ProxyRulesExpectation::Single(
1277          "socks4://socks.com:888",  // single proxy
1278          ""),                       // bypass rules
1279    },
1280
1281    {
1282      TEST_DESC("Treat all hostname patterns as wildcard patterns"),
1283
1284      // Input.
1285      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1286          "NoProxyFor=google.com,kde.org,<local>\n",
1287      {},                                      // env_values
1288
1289      // Expected result.
1290      ProxyConfigService::CONFIG_VALID,
1291      false,                                   // auto_detect
1292      GURL(),                                  // pac_url
1293      ProxyRulesExpectation::PerScheme(
1294          "www.google.com:80",              // http
1295          "",                               // https
1296          "",                               // ftp
1297          "*google.com,*kde.org,<local>"),  // bypass rules
1298    },
1299
1300    {
1301      TEST_DESC("Allow trailing whitespace after boolean value"),
1302
1303      // Input.
1304      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1305          "NoProxyFor=.google.com\nReversedException=true  \n",
1306      {},                                      // env_values
1307
1308      // Expected result.
1309      ProxyConfigService::CONFIG_VALID,
1310      false,                                   // auto_detect
1311      GURL(),                                  // pac_url
1312      ProxyRulesExpectation::PerSchemeWithBypassReversed(
1313          "www.google.com:80",  // http
1314          "",                   // https
1315          "",                   // ftp
1316          "*.google.com"),      // bypass rules
1317    },
1318
1319    {
1320      TEST_DESC("Ignore settings outside [Proxy Settings]"),
1321
1322      // Input.
1323      "httpsProxy=www.foo.com\n[Proxy Settings]\nProxyType=1\n"
1324          "httpProxy=www.google.com\n[Other Section]\nftpProxy=ftp.foo.com\n",
1325      {},                                      // env_values
1326
1327      // Expected result.
1328      ProxyConfigService::CONFIG_VALID,
1329      false,                                   // auto_detect
1330      GURL(),                                  // pac_url
1331      ProxyRulesExpectation::PerScheme(
1332          "www.google.com:80",  // http
1333          "",                   // https
1334          "",                   // ftp
1335          ""),                  // bypass rules
1336    },
1337
1338    {
1339      TEST_DESC("Handle CRLF line endings"),
1340
1341      // Input.
1342      "[Proxy Settings]\r\nProxyType=1\r\nhttpProxy=www.google.com\r\n",
1343      {},                                      // env_values
1344
1345      // Expected result.
1346      ProxyConfigService::CONFIG_VALID,
1347      false,                                   // auto_detect
1348      GURL(),                                  // pac_url
1349      ProxyRulesExpectation::PerScheme(
1350          "www.google.com:80",  // http
1351          "",                   // https
1352          "",                   // ftp
1353          ""),                  // bypass rules
1354    },
1355
1356    {
1357      TEST_DESC("Handle blank lines and mixed line endings"),
1358
1359      // Input.
1360      "[Proxy Settings]\r\n\nProxyType=1\n\r\nhttpProxy=www.google.com\n\n",
1361      {},                                      // env_values
1362
1363      // Expected result.
1364      ProxyConfigService::CONFIG_VALID,
1365      false,                                   // auto_detect
1366      GURL(),                                  // pac_url
1367      ProxyRulesExpectation::PerScheme(
1368          "www.google.com:80",  // http
1369          "",                   // https
1370          "",                   // ftp
1371          ""),                  // bypass rules
1372    },
1373
1374    {
1375      TEST_DESC("Handle localized settings"),
1376
1377      // Input.
1378      "[Proxy Settings]\nProxyType[$e]=1\nhttpProxy[$e]=www.google.com\n",
1379      {},                                      // env_values
1380
1381      // Expected result.
1382      ProxyConfigService::CONFIG_VALID,
1383      false,                                   // auto_detect
1384      GURL(),                                  // pac_url
1385      ProxyRulesExpectation::PerScheme(
1386          "www.google.com:80",  // http
1387          "",                   // https
1388          "",                   // ftp
1389          ""),                  // bypass rules
1390    },
1391
1392    {
1393      TEST_DESC("Ignore malformed localized settings"),
1394
1395      // Input.
1396      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1397          "httpsProxy$e]=www.foo.com\nftpProxy=ftp.foo.com\n",
1398      {},                                      // env_values
1399
1400      // Expected result.
1401      ProxyConfigService::CONFIG_VALID,
1402      false,                                   // auto_detect
1403      GURL(),                                  // pac_url
1404      ProxyRulesExpectation::PerScheme(
1405          "www.google.com:80",  // http
1406          "",                   // https
1407          "ftp.foo.com:80",     // ftp
1408          ""),                  // bypass rules
1409    },
1410
1411    {
1412      TEST_DESC("Handle strange whitespace"),
1413
1414      // Input.
1415      "[Proxy Settings]\nProxyType [$e] =2\n"
1416          "  Proxy Config Script =  http:// foo\n",
1417      {},                                      // env_values
1418
1419      // Expected result.
1420      ProxyConfigService::CONFIG_VALID,
1421      false,                                   // auto_detect
1422      GURL("http:// foo"),                     // pac_url
1423      ProxyRulesExpectation::Empty(),
1424    },
1425
1426    {
1427      TEST_DESC("Ignore all of a line which is too long"),
1428
1429      // Input.
1430      std::string("[Proxy Settings]\nProxyType=1\nftpProxy=ftp.foo.com\n") +
1431          long_line + "httpsProxy=www.foo.com\nhttpProxy=www.google.com\n",
1432      {},                                          // env_values
1433
1434      // Expected result.
1435      ProxyConfigService::CONFIG_VALID,
1436      false,                                       // auto_detect
1437      GURL(),                                      // pac_url
1438      ProxyRulesExpectation::PerScheme(
1439          "www.google.com:80",  // http
1440          "",                   // https
1441          "ftp.foo.com:80",     // ftp
1442          ""),                  // bypass rules
1443    },
1444
1445    {
1446      TEST_DESC("Indirect Proxy - no env vars set"),
1447
1448      // Input.
1449      "[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n"
1450          "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n",
1451      {},                                      // env_values
1452
1453      // Expected result.
1454      ProxyConfigService::CONFIG_VALID,
1455      false,                                   // auto_detect
1456      GURL(),                                  // pac_url
1457      ProxyRulesExpectation::Empty(),
1458    },
1459
1460    {
1461      TEST_DESC("Indirect Proxy - with env vars set"),
1462
1463      // Input.
1464      "[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n"
1465          "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n",
1466      {  // env_values
1467        NULL,  // DESKTOP_SESSION
1468        NULL,  // HOME
1469        NULL,  // KDEHOME
1470        NULL,  // KDE_SESSION_VERSION
1471        NULL,  // auto_proxy
1472        NULL,  // all_proxy
1473        "www.normal.com",  // http_proxy
1474        "www.secure.com",  // https_proxy
1475        "ftp.foo.com",  // ftp_proxy
1476        NULL, NULL,  // SOCKS
1477        ".google.com, .kde.org",  // no_proxy
1478      },
1479
1480      // Expected result.
1481      ProxyConfigService::CONFIG_VALID,
1482      false,                                   // auto_detect
1483      GURL(),                                  // pac_url
1484      ProxyRulesExpectation::PerScheme(
1485          "www.normal.com:80",           // http
1486          "www.secure.com:80",           // https
1487          "ftp.foo.com:80",              // ftp
1488          "*.google.com,*.kde.org"),     // bypass rules
1489    },
1490
1491  };
1492
1493  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
1494    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
1495                                    tests[i].description.c_str()));
1496    MockEnvironment* env = new MockEnvironment;
1497    env->values = tests[i].env_values;
1498    // Force the KDE getter to be used and tell it where the test is.
1499    env->values.DESKTOP_SESSION = "kde4";
1500    env->values.KDEHOME = kde_home_.value().c_str();
1501    SynchConfigGetter sync_config_getter(
1502        new ProxyConfigServiceLinux(env));
1503    ProxyConfig config;
1504    // Overwrite the kioslaverc file.
1505    file_util::WriteFile(kioslaverc_, tests[i].kioslaverc.c_str(),
1506                         tests[i].kioslaverc.length());
1507    sync_config_getter.SetupAndInitialFetch();
1508    ProxyConfigService::ConfigAvailability availability =
1509        sync_config_getter.SyncGetLatestProxyConfig(&config);
1510    EXPECT_EQ(tests[i].availability, availability);
1511
1512    if (availability == ProxyConfigService::CONFIG_VALID) {
1513      EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
1514      EXPECT_EQ(tests[i].pac_url, config.pac_url());
1515      EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
1516    }
1517  }
1518}
1519
1520TEST_F(ProxyConfigServiceLinuxTest, KDEHomePicker) {
1521  // Auto detect proxy settings.
1522  std::string slaverc3 = "[Proxy Settings]\nProxyType=3\n";
1523  // Valid PAC URL.
1524  std::string slaverc4 = "[Proxy Settings]\nProxyType=2\n"
1525                             "Proxy Config Script=http://wpad/wpad.dat\n";
1526  GURL slaverc4_pac_url("http://wpad/wpad.dat");
1527
1528  // Overwrite the .kde kioslaverc file.
1529  file_util::WriteFile(kioslaverc_, slaverc3.c_str(), slaverc3.length());
1530
1531  // If .kde4 exists it will mess up the first test. It should not, as
1532  // we created the directory for $HOME in the test setup.
1533  CHECK(!base::DirectoryExists(kde4_home_));
1534
1535  { SCOPED_TRACE("KDE4, no .kde4 directory, verify fallback");
1536    MockEnvironment* env = new MockEnvironment;
1537    env->values.DESKTOP_SESSION = "kde4";
1538    env->values.HOME = user_home_.value().c_str();
1539    SynchConfigGetter sync_config_getter(
1540        new ProxyConfigServiceLinux(env));
1541    ProxyConfig config;
1542    sync_config_getter.SetupAndInitialFetch();
1543    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1544              sync_config_getter.SyncGetLatestProxyConfig(&config));
1545    EXPECT_TRUE(config.auto_detect());
1546    EXPECT_EQ(GURL(), config.pac_url());
1547  }
1548
1549  // Now create .kde4 and put a kioslaverc in the config directory.
1550  // Note that its timestamp will be at least as new as the .kde one.
1551  base::CreateDirectory(kde4_config_);
1552  file_util::WriteFile(kioslaverc4_, slaverc4.c_str(), slaverc4.length());
1553  CHECK(base::PathExists(kioslaverc4_));
1554
1555  { SCOPED_TRACE("KDE4, .kde4 directory present, use it");
1556    MockEnvironment* env = new MockEnvironment;
1557    env->values.DESKTOP_SESSION = "kde4";
1558    env->values.HOME = user_home_.value().c_str();
1559    SynchConfigGetter sync_config_getter(
1560        new ProxyConfigServiceLinux(env));
1561    ProxyConfig config;
1562    sync_config_getter.SetupAndInitialFetch();
1563    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1564              sync_config_getter.SyncGetLatestProxyConfig(&config));
1565    EXPECT_FALSE(config.auto_detect());
1566    EXPECT_EQ(slaverc4_pac_url, config.pac_url());
1567  }
1568
1569  { SCOPED_TRACE("KDE3, .kde4 directory present, ignore it");
1570    MockEnvironment* env = new MockEnvironment;
1571    env->values.DESKTOP_SESSION = "kde";
1572    env->values.HOME = user_home_.value().c_str();
1573    SynchConfigGetter sync_config_getter(
1574        new ProxyConfigServiceLinux(env));
1575    ProxyConfig config;
1576    sync_config_getter.SetupAndInitialFetch();
1577    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1578              sync_config_getter.SyncGetLatestProxyConfig(&config));
1579    EXPECT_TRUE(config.auto_detect());
1580    EXPECT_EQ(GURL(), config.pac_url());
1581  }
1582
1583  { SCOPED_TRACE("KDE4, .kde4 directory present, KDEHOME set to .kde");
1584    MockEnvironment* env = new MockEnvironment;
1585    env->values.DESKTOP_SESSION = "kde4";
1586    env->values.HOME = user_home_.value().c_str();
1587    env->values.KDEHOME = kde_home_.value().c_str();
1588    SynchConfigGetter sync_config_getter(
1589        new ProxyConfigServiceLinux(env));
1590    ProxyConfig config;
1591    sync_config_getter.SetupAndInitialFetch();
1592    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1593              sync_config_getter.SyncGetLatestProxyConfig(&config));
1594    EXPECT_TRUE(config.auto_detect());
1595    EXPECT_EQ(GURL(), config.pac_url());
1596  }
1597
1598  // Finally, make the .kde4 config directory older than the .kde directory
1599  // and make sure we then use .kde instead of .kde4 since it's newer.
1600  base::TouchFile(kde4_config_, base::Time(), base::Time());
1601
1602  { SCOPED_TRACE("KDE4, very old .kde4 directory present, use .kde");
1603    MockEnvironment* env = new MockEnvironment;
1604    env->values.DESKTOP_SESSION = "kde4";
1605    env->values.HOME = user_home_.value().c_str();
1606    SynchConfigGetter sync_config_getter(
1607        new ProxyConfigServiceLinux(env));
1608    ProxyConfig config;
1609    sync_config_getter.SetupAndInitialFetch();
1610    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1611              sync_config_getter.SyncGetLatestProxyConfig(&config));
1612    EXPECT_TRUE(config.auto_detect());
1613    EXPECT_EQ(GURL(), config.pac_url());
1614  }
1615}
1616
1617}  // namespace net
1618