proxy_config_service_linux_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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_path.h"
14#include "base/file_util.h"
15#include "base/format_macros.h"
16#include "base/logging.h"
17#include "base/string_util.h"
18#include "base/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                    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 = 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    MessageLoop* file_loop = io_thread_.message_loop();
292    DCHECK_EQ(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(), io_thread_.message_loop_proxy(),
296        static_cast<MessageLoopForIO*>(file_loop));
297  }
298  // Synchronously gets the proxy config.
299  net::ProxyConfigService::ConfigAvailability SyncGetLatestProxyConfig(
300      net::ProxyConfig* config) {
301    io_thread_.message_loop()->PostTask(FROM_HERE,
302        base::Bind(&SynchConfigGetter::GetLatestConfigOnIOThread,
303                   base::Unretained(this)));
304    Wait();
305    *config = proxy_config_;
306    return get_latest_config_result_;
307  }
308
309 private:
310  // [Runs on |io_thread_|]
311  void Init() {
312    event_.Signal();
313  }
314
315  // Calls GetLatestProxyConfig, running on |io_thread_| Signals |event_|
316  // on completion.
317  void GetLatestConfigOnIOThread() {
318    get_latest_config_result_ =
319        config_service_->GetLatestProxyConfig(&proxy_config_);
320    event_.Signal();
321  }
322
323  // [Runs on |io_thread_|] Signals |event_| on cleanup completion.
324  void CleanUp() {
325    MessageLoop::current()->RunAllPending();
326    event_.Signal();
327  }
328
329  void Wait() {
330    event_.Wait();
331    event_.Reset();
332  }
333
334  base::WaitableEvent event_;
335  base::Thread io_thread_;
336
337  net::ProxyConfigServiceLinux* config_service_;
338
339  // The config obtained by |io_thread_| and read back by the main
340  // thread.
341  net::ProxyConfig proxy_config_;
342
343  // Return value from GetLatestProxyConfig().
344  net::ProxyConfigService::ConfigAvailability get_latest_config_result_;
345};
346
347namespace net {
348
349// This test fixture is only really needed for the KDEConfigParser test case,
350// but all the test cases with the same prefix ("ProxyConfigServiceLinuxTest")
351// must use the same test fixture class (also "ProxyConfigServiceLinuxTest").
352class ProxyConfigServiceLinuxTest : public PlatformTest {
353 protected:
354  virtual void SetUp() OVERRIDE {
355    PlatformTest::SetUp();
356    // Set up a temporary KDE home directory.
357    std::string prefix("ProxyConfigServiceLinuxTest_user_home");
358    file_util::CreateNewTempDirectory(prefix, &user_home_);
359    kde_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde"));
360    FilePath path = kde_home_.Append(FILE_PATH_LITERAL("share"));
361    path = path.Append(FILE_PATH_LITERAL("config"));
362    file_util::CreateDirectory(path);
363    kioslaverc_ = path.Append(FILE_PATH_LITERAL("kioslaverc"));
364    // Set up paths but do not create the directory for .kde4.
365    kde4_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde4"));
366    path = kde4_home_.Append(FILE_PATH_LITERAL("share"));
367    kde4_config_ = path.Append(FILE_PATH_LITERAL("config"));
368    kioslaverc4_ = kde4_config_.Append(FILE_PATH_LITERAL("kioslaverc"));
369  }
370
371  virtual void TearDown() OVERRIDE {
372    // Delete the temporary KDE home directory.
373    file_util::Delete(user_home_, true);
374    PlatformTest::TearDown();
375  }
376
377  FilePath user_home_;
378  // KDE3 paths.
379  FilePath kde_home_;
380  FilePath kioslaverc_;
381  // KDE4 paths.
382  FilePath kde4_home_;
383  FilePath kde4_config_;
384  FilePath kioslaverc4_;
385};
386
387// Builds an identifier for each test in an array.
388#define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc)
389
390TEST_F(ProxyConfigServiceLinuxTest, BasicGConfTest) {
391  std::vector<std::string> empty_ignores;
392
393  std::vector<std::string> google_ignores;
394  google_ignores.push_back("*.google.com");
395
396  // Inspired from proxy_config_service_win_unittest.cc.
397  // Very neat, but harder to track down failures though.
398  const struct {
399    // Short description to identify the test
400    std::string description;
401
402    // Input.
403    GConfValues values;
404
405    // Expected outputs (availability and fields of ProxyConfig).
406    ProxyConfigService::ConfigAvailability availability;
407    bool auto_detect;
408    GURL pac_url;
409    ProxyRulesExpectation proxy_rules;
410  } tests[] = {
411    {
412      TEST_DESC("No proxying"),
413      { // Input.
414        "none",                   // mode
415        "",                       // autoconfig_url
416        "", "", "", "",           // hosts
417        0, 0, 0, 0,               // ports
418        FALSE, FALSE, FALSE,      // use, same, auth
419        empty_ignores,            // ignore_hosts
420      },
421
422      // Expected result.
423      ProxyConfigService::CONFIG_VALID,
424      false,                      // auto_detect
425      GURL(),                     // pac_url
426      ProxyRulesExpectation::Empty(),
427    },
428
429    {
430      TEST_DESC("Auto detect"),
431      { // Input.
432        "auto",                   // mode
433        "",                       // autoconfig_url
434        "", "", "", "",           // hosts
435        0, 0, 0, 0,               // ports
436        FALSE, FALSE, FALSE,      // use, same, auth
437        empty_ignores,            // ignore_hosts
438      },
439
440      // Expected result.
441      ProxyConfigService::CONFIG_VALID,
442      true,                       // auto_detect
443      GURL(),                     // pac_url
444      ProxyRulesExpectation::Empty(),
445    },
446
447    {
448      TEST_DESC("Valid PAC URL"),
449      { // Input.
450        "auto",                      // mode
451        "http://wpad/wpad.dat",      // autoconfig_url
452        "", "", "", "",              // hosts
453        0, 0, 0, 0,                  // ports
454        FALSE, FALSE, FALSE,         // use, same, auth
455        empty_ignores,               // ignore_hosts
456      },
457
458      // Expected result.
459      ProxyConfigService::CONFIG_VALID,
460      false,                         // auto_detect
461      GURL("http://wpad/wpad.dat"),  // pac_url
462      ProxyRulesExpectation::Empty(),
463    },
464
465    {
466      TEST_DESC("Invalid PAC URL"),
467      { // Input.
468        "auto",                      // mode
469        "wpad.dat",                  // autoconfig_url
470        "", "", "", "",              // hosts
471        0, 0, 0, 0,                  // ports
472        FALSE, FALSE, FALSE,         // use, same, auth
473        empty_ignores,               // ignore_hosts
474      },
475
476      // Expected result.
477      ProxyConfigService::CONFIG_VALID,
478      false,                          // auto_detect
479      GURL(),                        // pac_url
480      ProxyRulesExpectation::Empty(),
481    },
482
483    {
484      TEST_DESC("Single-host in proxy list"),
485      { // Input.
486        "manual",                              // mode
487        "",                                    // autoconfig_url
488        "www.google.com", "", "", "",          // hosts
489        80, 0, 0, 0,                           // ports
490        TRUE, TRUE, FALSE,                     // use, same, auth
491        empty_ignores,                         // ignore_hosts
492      },
493
494      // Expected result.
495      ProxyConfigService::CONFIG_VALID,
496      false,                                   // auto_detect
497      GURL(),                                  // pac_url
498      ProxyRulesExpectation::Single(
499          "www.google.com:80",  // single proxy
500          ""),                  // bypass rules
501    },
502
503    {
504      TEST_DESC("use_http_proxy is honored"),
505      { // Input.
506        "manual",                              // mode
507        "",                                    // autoconfig_url
508        "www.google.com", "", "", "",          // hosts
509        80, 0, 0, 0,                           // ports
510        FALSE, TRUE, FALSE,                    // use, same, auth
511        empty_ignores,                         // ignore_hosts
512      },
513
514      // Expected result.
515      ProxyConfigService::CONFIG_VALID,
516      false,                                   // auto_detect
517      GURL(),                                  // pac_url
518      ProxyRulesExpectation::Empty(),
519    },
520
521    {
522      TEST_DESC("use_http_proxy and use_same_proxy are optional"),
523      { // Input.
524        "manual",                                     // mode
525        "",                                           // autoconfig_url
526        "www.google.com", "", "", "",                 // hosts
527        80, 0, 0, 0,                                  // ports
528        UNSET, UNSET, FALSE,                          // use, same, auth
529        empty_ignores,                                // ignore_hosts
530      },
531
532      // Expected result.
533      ProxyConfigService::CONFIG_VALID,
534      false,                                          // auto_detect
535      GURL(),                                         // pac_url
536      ProxyRulesExpectation::PerScheme(
537          "www.google.com:80",  // http
538          "",                   // https
539          "",                   // ftp
540          ""),                  // bypass rules
541    },
542
543    {
544      TEST_DESC("Single-host, different port"),
545      { // Input.
546        "manual",                                     // mode
547        "",                                           // autoconfig_url
548        "www.google.com", "", "", "",                 // hosts
549        88, 0, 0, 0,                                  // ports
550        TRUE, TRUE, FALSE,                            // use, same, auth
551        empty_ignores,                                // ignore_hosts
552      },
553
554      // Expected result.
555      ProxyConfigService::CONFIG_VALID,
556      false,                                          // auto_detect
557      GURL(),                                         // pac_url
558      ProxyRulesExpectation::Single(
559          "www.google.com:88",  // single proxy
560          ""),                  // bypass rules
561    },
562
563    {
564      TEST_DESC("Per-scheme proxy rules"),
565      { // Input.
566        "manual",                                     // mode
567        "",                                           // autoconfig_url
568        "www.google.com",                             // http_host
569        "www.foo.com",                                // secure_host
570        "ftp.foo.com",                                // ftp
571        "",                                           // socks
572        88, 110, 121, 0,                              // ports
573        TRUE, FALSE, FALSE,                           // use, same, auth
574        empty_ignores,                                // ignore_hosts
575      },
576
577      // Expected result.
578      ProxyConfigService::CONFIG_VALID,
579      false,                                          // auto_detect
580      GURL(),                                         // pac_url
581      ProxyRulesExpectation::PerScheme(
582          "www.google.com:88",  // http
583          "www.foo.com:110",    // https
584          "ftp.foo.com:121",    // ftp
585          ""),                  // bypass rules
586    },
587
588    {
589      TEST_DESC("socks"),
590      { // Input.
591        "manual",                                     // mode
592        "",                                           // autoconfig_url
593        "", "", "", "socks.com",                      // hosts
594        0, 0, 0, 99,                                  // ports
595        TRUE, FALSE, FALSE,                           // use, same, auth
596        empty_ignores,                                // ignore_hosts
597      },
598
599      // Expected result.
600      ProxyConfigService::CONFIG_VALID,
601      false,                                          // auto_detect
602      GURL(),                                         // pac_url
603      ProxyRulesExpectation::Single(
604          "socks5://socks.com:99",  // single proxy
605          "")                       // bypass rules
606    },
607
608    {
609      TEST_DESC("Per-scheme proxy rules with fallback to SOCKS"),
610      { // Input.
611        "manual",                                     // mode
612        "",                                           // autoconfig_url
613        "www.google.com",                             // http_host
614        "www.foo.com",                                // secure_host
615        "ftp.foo.com",                                // ftp
616        "foobar.net",                                 // socks
617        88, 110, 121, 99,                             // ports
618        TRUE, FALSE, FALSE,                           // use, same, auth
619        empty_ignores,                                // ignore_hosts
620      },
621
622      // Expected result.
623      ProxyConfigService::CONFIG_VALID,
624      false,                                          // auto_detect
625      GURL(),                                         // pac_url
626      ProxyRulesExpectation::PerSchemeWithSocks(
627          "www.google.com:88",      // http
628          "www.foo.com:110",        // https
629          "ftp.foo.com:121",        // ftp
630          "socks5://foobar.net:99", // socks
631          ""),                      // bypass rules
632    },
633
634    {
635      TEST_DESC("Per-scheme proxy rules (just HTTP) with fallback to SOCKS"),
636      { // Input.
637        "manual",                                     // mode
638        "",                                           // autoconfig_url
639        "www.google.com",                             // http_host
640        "",                                           // secure_host
641        "",                                           // ftp
642        "foobar.net",                                 // socks
643        88, 0, 0, 99,                                 // ports
644        TRUE, FALSE, FALSE,                           // use, same, auth
645        empty_ignores,                                // ignore_hosts
646      },
647
648      // Expected result.
649      ProxyConfigService::CONFIG_VALID,
650      false,                                          // auto_detect
651      GURL(),                                         // pac_url
652      ProxyRulesExpectation::PerSchemeWithSocks(
653          "www.google.com:88",      // http
654          "",                       // https
655          "",                       // ftp
656          "socks5://foobar.net:99", // socks
657          ""),                      // bypass rules
658    },
659
660    {
661      TEST_DESC("Bypass *.google.com"),
662      { // Input.
663        "manual",                                     // mode
664        "",                                           // autoconfig_url
665        "www.google.com", "", "", "",                 // hosts
666        80, 0, 0, 0,                                  // ports
667        TRUE, TRUE, FALSE,                            // use, same, auth
668        google_ignores,                               // ignore_hosts
669      },
670
671      ProxyConfigService::CONFIG_VALID,
672      false,                                          // auto_detect
673      GURL(),                                         // pac_url
674      ProxyRulesExpectation::Single(
675          "www.google.com:80",   // single proxy
676          "*.google.com"),       // bypass rules
677    },
678  };
679
680  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
681    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
682                                    tests[i].description.c_str()));
683    MockEnvironment* env = new MockEnvironment;
684    MockSettingGetter* setting_getter = new MockSettingGetter;
685    SynchConfigGetter sync_config_getter(
686        new ProxyConfigServiceLinux(env, setting_getter));
687    ProxyConfig config;
688    setting_getter->values = tests[i].values;
689    sync_config_getter.SetupAndInitialFetch();
690    ProxyConfigService::ConfigAvailability availability =
691        sync_config_getter.SyncGetLatestProxyConfig(&config);
692    EXPECT_EQ(tests[i].availability, availability);
693
694    if (availability == ProxyConfigService::CONFIG_VALID) {
695      EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
696      EXPECT_EQ(tests[i].pac_url, config.pac_url());
697      EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
698    }
699  }
700}
701
702TEST_F(ProxyConfigServiceLinuxTest, BasicEnvTest) {
703  // Inspired from proxy_config_service_win_unittest.cc.
704  const struct {
705    // Short description to identify the test
706    std::string description;
707
708    // Input.
709    EnvVarValues values;
710
711    // Expected outputs (availability and fields of ProxyConfig).
712    ProxyConfigService::ConfigAvailability availability;
713    bool auto_detect;
714    GURL pac_url;
715    ProxyRulesExpectation proxy_rules;
716  } tests[] = {
717    {
718      TEST_DESC("No proxying"),
719      { // Input.
720        NULL,  // DESKTOP_SESSION
721        NULL,  // HOME
722        NULL,  // KDEHOME
723        NULL,  // KDE_SESSION_VERSION
724        NULL,  // auto_proxy
725        NULL,  // all_proxy
726        NULL, NULL, NULL,  // per-proto proxies
727        NULL, NULL,  // SOCKS
728        "*",  // no_proxy
729      },
730
731      // Expected result.
732      ProxyConfigService::CONFIG_VALID,
733      false,                      // auto_detect
734      GURL(),                     // pac_url
735      ProxyRulesExpectation::Empty(),
736    },
737
738    {
739      TEST_DESC("Auto detect"),
740      { // Input.
741        NULL,  // DESKTOP_SESSION
742        NULL,  // HOME
743        NULL,  // KDEHOME
744        NULL,  // KDE_SESSION_VERSION
745        "",    // auto_proxy
746        NULL,  // all_proxy
747        NULL, NULL, NULL,  // per-proto proxies
748        NULL, NULL,  // SOCKS
749        NULL,  // no_proxy
750      },
751
752      // Expected result.
753      ProxyConfigService::CONFIG_VALID,
754      true,                       // auto_detect
755      GURL(),                     // pac_url
756      ProxyRulesExpectation::Empty(),
757    },
758
759    {
760      TEST_DESC("Valid PAC URL"),
761      { // Input.
762        NULL,  // DESKTOP_SESSION
763        NULL,  // HOME
764        NULL,  // KDEHOME
765        NULL,  // KDE_SESSION_VERSION
766        "http://wpad/wpad.dat",  // auto_proxy
767        NULL,  // all_proxy
768        NULL, NULL, NULL,  // per-proto proxies
769        NULL, NULL,  // SOCKS
770        NULL,  // no_proxy
771      },
772
773      // Expected result.
774      ProxyConfigService::CONFIG_VALID,
775      false,                         // auto_detect
776      GURL("http://wpad/wpad.dat"),  // pac_url
777      ProxyRulesExpectation::Empty(),
778    },
779
780    {
781      TEST_DESC("Invalid PAC URL"),
782      { // Input.
783        NULL,  // DESKTOP_SESSION
784        NULL,  // HOME
785        NULL,  // KDEHOME
786        NULL,  // KDE_SESSION_VERSION
787        "wpad.dat",  // auto_proxy
788        NULL,  // all_proxy
789        NULL, NULL, NULL,  // per-proto proxies
790        NULL, NULL,  // SOCKS
791        NULL,  // no_proxy
792      },
793
794      // Expected result.
795      ProxyConfigService::CONFIG_VALID,
796      false,                       // auto_detect
797      GURL(),                     // pac_url
798      ProxyRulesExpectation::Empty(),
799    },
800
801    {
802      TEST_DESC("Single-host in proxy list"),
803      { // Input.
804        NULL,  // DESKTOP_SESSION
805        NULL,  // HOME
806        NULL,  // KDEHOME
807        NULL,  // KDE_SESSION_VERSION
808        NULL,  // auto_proxy
809        "www.google.com",  // all_proxy
810        NULL, NULL, NULL,  // per-proto proxies
811        NULL, NULL,  // SOCKS
812        NULL,  // no_proxy
813      },
814
815      // Expected result.
816      ProxyConfigService::CONFIG_VALID,
817      false,                                   // auto_detect
818      GURL(),                                  // pac_url
819      ProxyRulesExpectation::Single(
820          "www.google.com:80",  // single proxy
821          ""),                  // bypass rules
822    },
823
824    {
825      TEST_DESC("Single-host, different port"),
826      { // Input.
827        NULL,  // DESKTOP_SESSION
828        NULL,  // HOME
829        NULL,  // KDEHOME
830        NULL,  // KDE_SESSION_VERSION
831        NULL,  // auto_proxy
832        "www.google.com:99",  // all_proxy
833        NULL, NULL, NULL,  // per-proto proxies
834        NULL, NULL,  // SOCKS
835        NULL,  // no_proxy
836      },
837
838      // Expected result.
839      ProxyConfigService::CONFIG_VALID,
840      false,                                   // auto_detect
841      GURL(),                                  // pac_url
842      ProxyRulesExpectation::Single(
843          "www.google.com:99",  // single
844          ""),                  // bypass rules
845    },
846
847    {
848      TEST_DESC("Tolerate a scheme"),
849      { // Input.
850        NULL,  // DESKTOP_SESSION
851        NULL,  // HOME
852        NULL,  // KDEHOME
853        NULL,  // KDE_SESSION_VERSION
854        NULL,  // auto_proxy
855        "http://www.google.com:99",  // all_proxy
856        NULL, NULL, NULL,  // per-proto proxies
857        NULL, NULL,  // SOCKS
858        NULL,  // no_proxy
859      },
860
861      // Expected result.
862      ProxyConfigService::CONFIG_VALID,
863      false,                                   // auto_detect
864      GURL(),                                  // pac_url
865      ProxyRulesExpectation::Single(
866          "www.google.com:99",  // single proxy
867          ""),                  // bypass rules
868    },
869
870    {
871      TEST_DESC("Per-scheme proxy rules"),
872      { // Input.
873        NULL,  // DESKTOP_SESSION
874        NULL,  // HOME
875        NULL,  // KDEHOME
876        NULL,  // KDE_SESSION_VERSION
877        NULL,  // auto_proxy
878        NULL,  // all_proxy
879        "www.google.com:80", "www.foo.com:110", "ftp.foo.com:121",  // per-proto
880        NULL, NULL,  // SOCKS
881        NULL,  // no_proxy
882      },
883
884      // Expected result.
885      ProxyConfigService::CONFIG_VALID,
886      false,                                   // auto_detect
887      GURL(),                                  // pac_url
888      ProxyRulesExpectation::PerScheme(
889          "www.google.com:80",  // http
890          "www.foo.com:110",    // https
891          "ftp.foo.com:121",    // ftp
892          ""),                  // bypass rules
893    },
894
895    {
896      TEST_DESC("socks"),
897      { // Input.
898        NULL,  // DESKTOP_SESSION
899        NULL,  // HOME
900        NULL,  // KDEHOME
901        NULL,  // KDE_SESSION_VERSION
902        NULL,  // auto_proxy
903        "",  // all_proxy
904        NULL, NULL, NULL,  // per-proto proxies
905        "socks.com:888", NULL,  // SOCKS
906        NULL,  // no_proxy
907      },
908
909      // Expected result.
910      ProxyConfigService::CONFIG_VALID,
911      false,                                   // auto_detect
912      GURL(),                                  // pac_url
913      ProxyRulesExpectation::Single(
914          "socks5://socks.com:888",  // single proxy
915          ""),                       // bypass rules
916    },
917
918    {
919      TEST_DESC("socks4"),
920      { // Input.
921        NULL,  // DESKTOP_SESSION
922        NULL,  // HOME
923        NULL,  // KDEHOME
924        NULL,  // KDE_SESSION_VERSION
925        NULL,  // auto_proxy
926        "",  // all_proxy
927        NULL, NULL, NULL,  // per-proto proxies
928        "socks.com:888", "4",  // SOCKS
929        NULL,  // no_proxy
930      },
931
932      // Expected result.
933      ProxyConfigService::CONFIG_VALID,
934      false,                                   // auto_detect
935      GURL(),                                  // pac_url
936      ProxyRulesExpectation::Single(
937          "socks4://socks.com:888",  // single proxy
938          ""),                       // bypass rules
939    },
940
941    {
942      TEST_DESC("socks default port"),
943      { // Input.
944        NULL,  // DESKTOP_SESSION
945        NULL,  // HOME
946        NULL,  // KDEHOME
947        NULL,  // KDE_SESSION_VERSION
948        NULL,  // auto_proxy
949        "",  // all_proxy
950        NULL, NULL, NULL,  // per-proto proxies
951        "socks.com", NULL,  // SOCKS
952        NULL,  // no_proxy
953      },
954
955      // Expected result.
956      ProxyConfigService::CONFIG_VALID,
957      false,                                   // auto_detect
958      GURL(),                                  // pac_url
959      ProxyRulesExpectation::Single(
960          "socks5://socks.com:1080",  // single proxy
961          ""),                        // bypass rules
962    },
963
964    {
965      TEST_DESC("bypass"),
966      { // Input.
967        NULL,  // DESKTOP_SESSION
968        NULL,  // HOME
969        NULL,  // KDEHOME
970        NULL,  // KDE_SESSION_VERSION
971        NULL,  // auto_proxy
972        "www.google.com",  // all_proxy
973        NULL, NULL, NULL,  // per-proto
974        NULL, NULL,  // SOCKS
975        ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8",  // no_proxy
976      },
977
978      // Expected result.
979      ProxyConfigService::CONFIG_VALID,
980      false,                      // auto_detect
981      GURL(),                     // pac_url
982      ProxyRulesExpectation::Single(
983          "www.google.com:80",
984          "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"),
985    },
986  };
987
988  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
989    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
990                                    tests[i].description.c_str()));
991    MockEnvironment* env = new MockEnvironment;
992    MockSettingGetter* setting_getter = new MockSettingGetter;
993    SynchConfigGetter sync_config_getter(
994        new ProxyConfigServiceLinux(env, setting_getter));
995    ProxyConfig config;
996    env->values = tests[i].values;
997    sync_config_getter.SetupAndInitialFetch();
998    ProxyConfigService::ConfigAvailability availability =
999        sync_config_getter.SyncGetLatestProxyConfig(&config);
1000    EXPECT_EQ(tests[i].availability, availability);
1001
1002    if (availability == ProxyConfigService::CONFIG_VALID) {
1003      EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
1004      EXPECT_EQ(tests[i].pac_url, config.pac_url());
1005      EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
1006    }
1007  }
1008}
1009
1010TEST_F(ProxyConfigServiceLinuxTest, GconfNotification) {
1011  MockEnvironment* env = new MockEnvironment;
1012  MockSettingGetter* setting_getter = new MockSettingGetter;
1013  ProxyConfigServiceLinux* service =
1014      new ProxyConfigServiceLinux(env, setting_getter);
1015  SynchConfigGetter sync_config_getter(service);
1016  ProxyConfig config;
1017
1018  // Start with no proxy.
1019  setting_getter->values.mode = "none";
1020  sync_config_getter.SetupAndInitialFetch();
1021  EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1022            sync_config_getter.SyncGetLatestProxyConfig(&config));
1023  EXPECT_FALSE(config.auto_detect());
1024
1025  // Now set to auto-detect.
1026  setting_getter->values.mode = "auto";
1027  // Simulate setting change notification callback.
1028  service->OnCheckProxyConfigSettings();
1029  EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1030            sync_config_getter.SyncGetLatestProxyConfig(&config));
1031  EXPECT_TRUE(config.auto_detect());
1032}
1033
1034TEST_F(ProxyConfigServiceLinuxTest, KDEConfigParser) {
1035  // One of the tests below needs a worst-case long line prefix. We build it
1036  // programmatically so that it will always be the right size.
1037  std::string long_line;
1038  size_t limit = ProxyConfigServiceLinux::SettingGetter::BUFFER_SIZE - 1;
1039  for (size_t i = 0; i < limit; ++i)
1040    long_line += "-";
1041
1042  // Inspired from proxy_config_service_win_unittest.cc.
1043  const struct {
1044    // Short description to identify the test
1045    std::string description;
1046
1047    // Input.
1048    std::string kioslaverc;
1049    EnvVarValues env_values;
1050
1051    // Expected outputs (availability and fields of ProxyConfig).
1052    ProxyConfigService::ConfigAvailability availability;
1053    bool auto_detect;
1054    GURL pac_url;
1055    ProxyRulesExpectation proxy_rules;
1056  } tests[] = {
1057    {
1058      TEST_DESC("No proxying"),
1059
1060      // Input.
1061      "[Proxy Settings]\nProxyType=0\n",
1062      {},                                      // env_values
1063
1064      // Expected result.
1065      ProxyConfigService::CONFIG_VALID,
1066      false,                      // auto_detect
1067      GURL(),                     // pac_url
1068      ProxyRulesExpectation::Empty(),
1069    },
1070
1071    {
1072      TEST_DESC("Auto detect"),
1073
1074      // Input.
1075      "[Proxy Settings]\nProxyType=3\n",
1076      {},                                      // env_values
1077
1078      // Expected result.
1079      ProxyConfigService::CONFIG_VALID,
1080      true,                       // auto_detect
1081      GURL(),                     // pac_url
1082      ProxyRulesExpectation::Empty(),
1083    },
1084
1085    {
1086      TEST_DESC("Valid PAC URL"),
1087
1088      // Input.
1089      "[Proxy Settings]\nProxyType=2\n"
1090          "Proxy Config Script=http://wpad/wpad.dat\n",
1091      {},                                      // env_values
1092
1093      // Expected result.
1094      ProxyConfigService::CONFIG_VALID,
1095      false,                         // auto_detect
1096      GURL("http://wpad/wpad.dat"),  // pac_url
1097      ProxyRulesExpectation::Empty(),
1098    },
1099
1100    {
1101      TEST_DESC("Valid PAC file without file://"),
1102
1103      // Input.
1104      "[Proxy Settings]\nProxyType=2\n"
1105          "Proxy Config Script=/wpad/wpad.dat\n",
1106      {},                                      // env_values
1107
1108      // Expected result.
1109      ProxyConfigService::CONFIG_VALID,
1110      false,                         // auto_detect
1111      GURL("file:///wpad/wpad.dat"),  // pac_url
1112      ProxyRulesExpectation::Empty(),
1113    },
1114
1115    {
1116      TEST_DESC("Per-scheme proxy rules"),
1117
1118      // Input.
1119      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1120          "httpsProxy=www.foo.com\nftpProxy=ftp.foo.com\n",
1121      {},                                      // env_values
1122
1123      // Expected result.
1124      ProxyConfigService::CONFIG_VALID,
1125      false,                                   // auto_detect
1126      GURL(),                                  // pac_url
1127      ProxyRulesExpectation::PerScheme(
1128          "www.google.com:80",  // http
1129          "www.foo.com:80",     // https
1130          "ftp.foo.com:80",     // http
1131          ""),                  // bypass rules
1132    },
1133
1134    {
1135      TEST_DESC("Only HTTP proxy specified"),
1136
1137      // Input.
1138      "[Proxy Settings]\nProxyType=1\n"
1139          "httpProxy=www.google.com\n",
1140      {},                                      // env_values
1141
1142      // Expected result.
1143      ProxyConfigService::CONFIG_VALID,
1144      false,                                   // auto_detect
1145      GURL(),                                  // pac_url
1146      ProxyRulesExpectation::PerScheme(
1147          "www.google.com:80",  // http
1148          "",                   // https
1149          "",                   // ftp
1150          ""),                  // bypass rules
1151    },
1152
1153    {
1154      TEST_DESC("Only HTTP proxy specified, different port"),
1155
1156      // Input.
1157      "[Proxy Settings]\nProxyType=1\n"
1158          "httpProxy=www.google.com:88\n",
1159      {},                                      // env_values
1160
1161      // Expected result.
1162      ProxyConfigService::CONFIG_VALID,
1163      false,                                   // auto_detect
1164      GURL(),                                  // pac_url
1165      ProxyRulesExpectation::PerScheme(
1166          "www.google.com:88",  // http
1167          "",                   // https
1168          "",                   // ftp
1169          ""),                  // bypass rules
1170    },
1171
1172    {
1173      TEST_DESC("Only HTTP proxy specified, different port, space-delimited"),
1174
1175      // Input.
1176      "[Proxy Settings]\nProxyType=1\n"
1177          "httpProxy=www.google.com 88\n",
1178      {},                                      // env_values
1179
1180      // Expected result.
1181      ProxyConfigService::CONFIG_VALID,
1182      false,                                   // auto_detect
1183      GURL(),                                  // pac_url
1184      ProxyRulesExpectation::PerScheme(
1185          "www.google.com:88",  // http
1186          "",                   // https
1187          "",                   // ftp
1188          ""),                  // bypass rules
1189    },
1190
1191    {
1192      TEST_DESC("Bypass *.google.com"),
1193
1194      // Input.
1195      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1196          "NoProxyFor=.google.com\n",
1197      {},                                      // env_values
1198
1199      // Expected result.
1200      ProxyConfigService::CONFIG_VALID,
1201      false,                                   // auto_detect
1202      GURL(),                                  // pac_url
1203      ProxyRulesExpectation::PerScheme(
1204          "www.google.com:80",  // http
1205          "",                   // https
1206          "",                   // ftp
1207          "*.google.com"),      // bypass rules
1208    },
1209
1210    {
1211      TEST_DESC("Bypass *.google.com and *.kde.org"),
1212
1213      // Input.
1214      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1215          "NoProxyFor=.google.com,.kde.org\n",
1216      {},                                      // env_values
1217
1218      // Expected result.
1219      ProxyConfigService::CONFIG_VALID,
1220      false,                                   // auto_detect
1221      GURL(),                                  // pac_url
1222      ProxyRulesExpectation::PerScheme(
1223          "www.google.com:80",           // http
1224          "",                            // https
1225          "",                            // ftp
1226          "*.google.com,*.kde.org"),     // bypass rules
1227    },
1228
1229    {
1230      TEST_DESC("Correctly parse bypass list with ReversedException"),
1231
1232      // Input.
1233      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1234          "NoProxyFor=.google.com\nReversedException=true\n",
1235      {},                                      // env_values
1236
1237      // Expected result.
1238      ProxyConfigService::CONFIG_VALID,
1239      false,                                   // auto_detect
1240      GURL(),                                  // pac_url
1241      ProxyRulesExpectation::PerSchemeWithBypassReversed(
1242          "www.google.com:80",  // http
1243          "",                   // https
1244          "",                   // ftp
1245          "*.google.com"),      // bypass rules
1246    },
1247
1248    {
1249      TEST_DESC("socks"),
1250
1251      // Input.
1252      "[Proxy Settings]\nProxyType=1\nsocksProxy=socks.com 888\n",
1253      {},                                      // env_values
1254
1255      // Expected result.
1256      ProxyConfigService::CONFIG_VALID,
1257      false,                                   // auto_detect
1258      GURL(),                                  // pac_url
1259      ProxyRulesExpectation::Single(
1260          "socks5://socks.com:888",  // single proxy
1261          ""),                       // bypass rules
1262    },
1263
1264    {
1265      TEST_DESC("socks4"),
1266
1267      // Input.
1268      "[Proxy Settings]\nProxyType=1\nsocksProxy=socks4://socks.com 888\n",
1269      {},                                      // env_values
1270
1271      // Expected result.
1272      ProxyConfigService::CONFIG_VALID,
1273      false,                                   // auto_detect
1274      GURL(),                                  // pac_url
1275      ProxyRulesExpectation::Single(
1276          "socks4://socks.com:888",  // single proxy
1277          ""),                       // bypass rules
1278    },
1279
1280    {
1281      TEST_DESC("Treat all hostname patterns as wildcard patterns"),
1282
1283      // Input.
1284      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1285          "NoProxyFor=google.com,kde.org,<local>\n",
1286      {},                                      // env_values
1287
1288      // Expected result.
1289      ProxyConfigService::CONFIG_VALID,
1290      false,                                   // auto_detect
1291      GURL(),                                  // pac_url
1292      ProxyRulesExpectation::PerScheme(
1293          "www.google.com:80",              // http
1294          "",                               // https
1295          "",                               // ftp
1296          "*google.com,*kde.org,<local>"),  // bypass rules
1297    },
1298
1299    {
1300      TEST_DESC("Allow trailing whitespace after boolean value"),
1301
1302      // Input.
1303      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1304          "NoProxyFor=.google.com\nReversedException=true  \n",
1305      {},                                      // env_values
1306
1307      // Expected result.
1308      ProxyConfigService::CONFIG_VALID,
1309      false,                                   // auto_detect
1310      GURL(),                                  // pac_url
1311      ProxyRulesExpectation::PerSchemeWithBypassReversed(
1312          "www.google.com:80",  // http
1313          "",                   // https
1314          "",                   // ftp
1315          "*.google.com"),      // bypass rules
1316    },
1317
1318    {
1319      TEST_DESC("Ignore settings outside [Proxy Settings]"),
1320
1321      // Input.
1322      "httpsProxy=www.foo.com\n[Proxy Settings]\nProxyType=1\n"
1323          "httpProxy=www.google.com\n[Other Section]\nftpProxy=ftp.foo.com\n",
1324      {},                                      // env_values
1325
1326      // Expected result.
1327      ProxyConfigService::CONFIG_VALID,
1328      false,                                   // auto_detect
1329      GURL(),                                  // pac_url
1330      ProxyRulesExpectation::PerScheme(
1331          "www.google.com:80",  // http
1332          "",                   // https
1333          "",                   // ftp
1334          ""),                  // bypass rules
1335    },
1336
1337    {
1338      TEST_DESC("Handle CRLF line endings"),
1339
1340      // Input.
1341      "[Proxy Settings]\r\nProxyType=1\r\nhttpProxy=www.google.com\r\n",
1342      {},                                      // env_values
1343
1344      // Expected result.
1345      ProxyConfigService::CONFIG_VALID,
1346      false,                                   // auto_detect
1347      GURL(),                                  // pac_url
1348      ProxyRulesExpectation::PerScheme(
1349          "www.google.com:80",  // http
1350          "",                   // https
1351          "",                   // ftp
1352          ""),                  // bypass rules
1353    },
1354
1355    {
1356      TEST_DESC("Handle blank lines and mixed line endings"),
1357
1358      // Input.
1359      "[Proxy Settings]\r\n\nProxyType=1\n\r\nhttpProxy=www.google.com\n\n",
1360      {},                                      // env_values
1361
1362      // Expected result.
1363      ProxyConfigService::CONFIG_VALID,
1364      false,                                   // auto_detect
1365      GURL(),                                  // pac_url
1366      ProxyRulesExpectation::PerScheme(
1367          "www.google.com:80",  // http
1368          "",                   // https
1369          "",                   // ftp
1370          ""),                  // bypass rules
1371    },
1372
1373    {
1374      TEST_DESC("Handle localized settings"),
1375
1376      // Input.
1377      "[Proxy Settings]\nProxyType[$e]=1\nhttpProxy[$e]=www.google.com\n",
1378      {},                                      // env_values
1379
1380      // Expected result.
1381      ProxyConfigService::CONFIG_VALID,
1382      false,                                   // auto_detect
1383      GURL(),                                  // pac_url
1384      ProxyRulesExpectation::PerScheme(
1385          "www.google.com:80",  // http
1386          "",                   // https
1387          "",                   // ftp
1388          ""),                  // bypass rules
1389    },
1390
1391    {
1392      TEST_DESC("Ignore malformed localized settings"),
1393
1394      // Input.
1395      "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com\n"
1396          "httpsProxy$e]=www.foo.com\nftpProxy=ftp.foo.com\n",
1397      {},                                      // env_values
1398
1399      // Expected result.
1400      ProxyConfigService::CONFIG_VALID,
1401      false,                                   // auto_detect
1402      GURL(),                                  // pac_url
1403      ProxyRulesExpectation::PerScheme(
1404          "www.google.com:80",  // http
1405          "",                   // https
1406          "ftp.foo.com:80",     // ftp
1407          ""),                  // bypass rules
1408    },
1409
1410    {
1411      TEST_DESC("Handle strange whitespace"),
1412
1413      // Input.
1414      "[Proxy Settings]\nProxyType [$e] =2\n"
1415          "  Proxy Config Script =  http:// foo\n",
1416      {},                                      // env_values
1417
1418      // Expected result.
1419      ProxyConfigService::CONFIG_VALID,
1420      false,                                   // auto_detect
1421      GURL("http:// foo"),                     // pac_url
1422      ProxyRulesExpectation::Empty(),
1423    },
1424
1425    {
1426      TEST_DESC("Ignore all of a line which is too long"),
1427
1428      // Input.
1429      std::string("[Proxy Settings]\nProxyType=1\nftpProxy=ftp.foo.com\n") +
1430          long_line + "httpsProxy=www.foo.com\nhttpProxy=www.google.com\n",
1431      {},                                          // env_values
1432
1433      // Expected result.
1434      ProxyConfigService::CONFIG_VALID,
1435      false,                                       // auto_detect
1436      GURL(),                                      // pac_url
1437      ProxyRulesExpectation::PerScheme(
1438          "www.google.com:80",  // http
1439          "",                   // https
1440          "ftp.foo.com:80",     // ftp
1441          ""),                  // bypass rules
1442    },
1443
1444    {
1445      TEST_DESC("Indirect Proxy - no env vars set"),
1446
1447      // Input.
1448      "[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n"
1449          "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n",
1450      {},                                      // env_values
1451
1452      // Expected result.
1453      ProxyConfigService::CONFIG_VALID,
1454      false,                                   // auto_detect
1455      GURL(),                                  // pac_url
1456      ProxyRulesExpectation::Empty(),
1457    },
1458
1459    {
1460      TEST_DESC("Indirect Proxy - with env vars set"),
1461
1462      // Input.
1463      "[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n"
1464          "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n",
1465      {  // env_values
1466        NULL,  // DESKTOP_SESSION
1467        NULL,  // HOME
1468        NULL,  // KDEHOME
1469        NULL,  // KDE_SESSION_VERSION
1470        NULL,  // auto_proxy
1471        NULL,  // all_proxy
1472        "www.normal.com",  // http_proxy
1473        "www.secure.com",  // https_proxy
1474        "ftp.foo.com",  // ftp_proxy
1475        NULL, NULL,  // SOCKS
1476        ".google.com, .kde.org",  // no_proxy
1477      },
1478
1479      // Expected result.
1480      ProxyConfigService::CONFIG_VALID,
1481      false,                                   // auto_detect
1482      GURL(),                                  // pac_url
1483      ProxyRulesExpectation::PerScheme(
1484          "www.normal.com:80",           // http
1485          "www.secure.com:80",           // https
1486          "ftp.foo.com:80",              // ftp
1487          "*.google.com,*.kde.org"),     // bypass rules
1488    },
1489
1490  };
1491
1492  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
1493    SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i,
1494                                    tests[i].description.c_str()));
1495    MockEnvironment* env = new MockEnvironment;
1496    env->values = tests[i].env_values;
1497    // Force the KDE getter to be used and tell it where the test is.
1498    env->values.DESKTOP_SESSION = "kde4";
1499    env->values.KDEHOME = kde_home_.value().c_str();
1500    SynchConfigGetter sync_config_getter(
1501        new ProxyConfigServiceLinux(env));
1502    ProxyConfig config;
1503    // Overwrite the kioslaverc file.
1504    file_util::WriteFile(kioslaverc_, tests[i].kioslaverc.c_str(),
1505                         tests[i].kioslaverc.length());
1506    sync_config_getter.SetupAndInitialFetch();
1507    ProxyConfigService::ConfigAvailability availability =
1508        sync_config_getter.SyncGetLatestProxyConfig(&config);
1509    EXPECT_EQ(tests[i].availability, availability);
1510
1511    if (availability == ProxyConfigService::CONFIG_VALID) {
1512      EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
1513      EXPECT_EQ(tests[i].pac_url, config.pac_url());
1514      EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
1515    }
1516  }
1517}
1518
1519TEST_F(ProxyConfigServiceLinuxTest, KDEHomePicker) {
1520  // Auto detect proxy settings.
1521  std::string slaverc3 = "[Proxy Settings]\nProxyType=3\n";
1522  // Valid PAC URL.
1523  std::string slaverc4 = "[Proxy Settings]\nProxyType=2\n"
1524                             "Proxy Config Script=http://wpad/wpad.dat\n";
1525  GURL slaverc4_pac_url("http://wpad/wpad.dat");
1526
1527  // Overwrite the .kde kioslaverc file.
1528  file_util::WriteFile(kioslaverc_, slaverc3.c_str(), slaverc3.length());
1529
1530  // If .kde4 exists it will mess up the first test. It should not, as
1531  // we created the directory for $HOME in the test setup.
1532  CHECK(!file_util::DirectoryExists(kde4_home_));
1533
1534  { SCOPED_TRACE("KDE4, no .kde4 directory, verify fallback");
1535    MockEnvironment* env = new MockEnvironment;
1536    env->values.DESKTOP_SESSION = "kde4";
1537    env->values.HOME = user_home_.value().c_str();
1538    SynchConfigGetter sync_config_getter(
1539        new ProxyConfigServiceLinux(env));
1540    ProxyConfig config;
1541    sync_config_getter.SetupAndInitialFetch();
1542    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1543              sync_config_getter.SyncGetLatestProxyConfig(&config));
1544    EXPECT_TRUE(config.auto_detect());
1545    EXPECT_EQ(GURL(), config.pac_url());
1546  }
1547
1548  // Now create .kde4 and put a kioslaverc in the config directory.
1549  // Note that its timestamp will be at least as new as the .kde one.
1550  file_util::CreateDirectory(kde4_config_);
1551  file_util::WriteFile(kioslaverc4_, slaverc4.c_str(), slaverc4.length());
1552  CHECK(file_util::PathExists(kioslaverc4_));
1553
1554  { SCOPED_TRACE("KDE4, .kde4 directory present, use it");
1555    MockEnvironment* env = new MockEnvironment;
1556    env->values.DESKTOP_SESSION = "kde4";
1557    env->values.HOME = user_home_.value().c_str();
1558    SynchConfigGetter sync_config_getter(
1559        new ProxyConfigServiceLinux(env));
1560    ProxyConfig config;
1561    sync_config_getter.SetupAndInitialFetch();
1562    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1563              sync_config_getter.SyncGetLatestProxyConfig(&config));
1564    EXPECT_FALSE(config.auto_detect());
1565    EXPECT_EQ(slaverc4_pac_url, config.pac_url());
1566  }
1567
1568  { SCOPED_TRACE("KDE3, .kde4 directory present, ignore it");
1569    MockEnvironment* env = new MockEnvironment;
1570    env->values.DESKTOP_SESSION = "kde";
1571    env->values.HOME = user_home_.value().c_str();
1572    SynchConfigGetter sync_config_getter(
1573        new ProxyConfigServiceLinux(env));
1574    ProxyConfig config;
1575    sync_config_getter.SetupAndInitialFetch();
1576    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1577              sync_config_getter.SyncGetLatestProxyConfig(&config));
1578    EXPECT_TRUE(config.auto_detect());
1579    EXPECT_EQ(GURL(), config.pac_url());
1580  }
1581
1582  { SCOPED_TRACE("KDE4, .kde4 directory present, KDEHOME set to .kde");
1583    MockEnvironment* env = new MockEnvironment;
1584    env->values.DESKTOP_SESSION = "kde4";
1585    env->values.HOME = user_home_.value().c_str();
1586    env->values.KDEHOME = kde_home_.value().c_str();
1587    SynchConfigGetter sync_config_getter(
1588        new ProxyConfigServiceLinux(env));
1589    ProxyConfig config;
1590    sync_config_getter.SetupAndInitialFetch();
1591    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1592              sync_config_getter.SyncGetLatestProxyConfig(&config));
1593    EXPECT_TRUE(config.auto_detect());
1594    EXPECT_EQ(GURL(), config.pac_url());
1595  }
1596
1597  // Finally, make the .kde4 config directory older than the .kde directory
1598  // and make sure we then use .kde instead of .kde4 since it's newer.
1599  file_util::SetLastModifiedTime(kde4_config_, base::Time());
1600
1601  { SCOPED_TRACE("KDE4, very old .kde4 directory present, use .kde");
1602    MockEnvironment* env = new MockEnvironment;
1603    env->values.DESKTOP_SESSION = "kde4";
1604    env->values.HOME = user_home_.value().c_str();
1605    SynchConfigGetter sync_config_getter(
1606        new ProxyConfigServiceLinux(env));
1607    ProxyConfig config;
1608    sync_config_getter.SetupAndInitialFetch();
1609    EXPECT_EQ(ProxyConfigService::CONFIG_VALID,
1610              sync_config_getter.SyncGetLatestProxyConfig(&config));
1611    EXPECT_TRUE(config.auto_detect());
1612    EXPECT_EQ(GURL(), config.pac_url());
1613  }
1614}
1615
1616}  // namespace net
1617