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