1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/proxy_config_service_impl.h"
6
7#include <map>
8#include <string>
9#include <vector>
10
11#include "base/format_macros.h"
12#include "base/logging.h"
13#include "base/string_util.h"
14#include "base/stringprintf.h"
15#include "chrome/browser/chromeos/cros/cros_library.h"
16#include "content/browser/browser_thread.h"
17#include "content/common/json_value_serializer.h"
18#include "net/proxy/proxy_config_service_common_unittest.h"
19#include "testing/gtest/include/gtest/gtest.h"
20#include "testing/platform_test.h"
21
22namespace chromeos {
23
24namespace {
25
26struct Input {  // Fields of chromeos::ProxyConfigServiceImpl::ProxyConfig.
27  ProxyConfigServiceImpl::ProxyConfig::Mode mode;
28  const char* pac_url;
29  const char* single_uri;
30  const char* http_uri;
31  const char* https_uri;
32  const char* ftp_uri;
33  const char* socks_uri;
34  const char* bypass_rules;
35};
36
37// Builds an identifier for each test in an array.
38#define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc)
39
40// Shortcuts to declare enums within chromeos's ProxyConfig.
41#define MK_MODE(mode) ProxyConfigServiceImpl::ProxyConfig::MODE_##mode
42#define MK_SRC(src) ProxyConfigServiceImpl::ProxyConfig::SOURCE_##src
43#define MK_SCHM(scheme) net::ProxyServer::SCHEME_##scheme
44
45// Inspired from net/proxy/proxy_config_service_linux_unittest.cc.
46const struct {
47  // Short description to identify the test
48  std::string description;
49
50  bool is_valid;
51  bool test_read_write_access;
52
53  Input input;
54
55  // Expected outputs from fields of net::ProxyConfig (via IO).
56  bool auto_detect;
57  GURL pac_url;
58  net::ProxyRulesExpectation proxy_rules;
59} tests[] = {
60  {
61    TEST_DESC("No proxying"),
62
63    true,  // is_valid
64    true,  // test_read_write_access
65
66    { // Input.
67      MK_MODE(DIRECT),  // mode
68    },
69
70    // Expected result.
71    false,                                   // auto_detect
72    GURL(),                                  // pac_url
73    net::ProxyRulesExpectation::Empty(),     // proxy_rules
74  },
75
76  {
77    TEST_DESC("Auto detect"),
78
79    true,  // is_valid
80    true,  // test_read_write_access
81
82    { // Input.
83      MK_MODE(AUTO_DETECT),  // mode
84    },
85
86    // Expected result.
87    true,                                    // auto_detect
88    GURL(),                                  // pac_url
89    net::ProxyRulesExpectation::Empty(),     // proxy_rules
90  },
91
92  {
93    TEST_DESC("Valid PAC URL"),
94
95    true,  // is_valid
96    true,  // test_read_write_access
97
98    { // Input.
99      MK_MODE(PAC_SCRIPT),     // mode
100      "http://wpad/wpad.dat",  // pac_url
101    },
102
103    // Expected result.
104    false,                                   // auto_detect
105    GURL("http://wpad/wpad.dat"),            // pac_url
106    net::ProxyRulesExpectation::Empty(),     // proxy_rules
107  },
108
109  {
110    TEST_DESC("Invalid PAC URL"),
111
112    false,  // is_valid
113    false,  // test_read_write_access
114
115    { // Input.
116      MK_MODE(PAC_SCRIPT),  // mode
117      "wpad.dat",           // pac_url
118    },
119
120    // Expected result.
121    false,                                   // auto_detect
122    GURL(),                                  // pac_url
123    net::ProxyRulesExpectation::Empty(),     // proxy_rules
124  },
125
126  {
127    TEST_DESC("Single-host in proxy list"),
128
129    true,  // is_valid
130    true,  // test_read_write_access
131
132    { // Input.
133      MK_MODE(SINGLE_PROXY),  // mode
134      NULL,                   // pac_url
135      "www.google.com",       // single_uri
136    },
137
138    // Expected result.
139    false,                                   // auto_detect
140    GURL(),                                  // pac_url
141    net::ProxyRulesExpectation::Single(      // proxy_rules
142        "www.google.com:80",  // single proxy
143        ""),                  // bypass rules
144  },
145
146  {
147    TEST_DESC("Single-host, different port"),
148
149    true,   // is_valid
150    false,  // test_read_write_access
151
152    { // Input.
153      MK_MODE(SINGLE_PROXY),  // mode
154      NULL,                   // pac_url
155      "www.google.com:99",    // single_uri
156    },
157
158    // Expected result.
159    false,                                   // auto_detect
160    GURL(),                                  // pac_url
161    net::ProxyRulesExpectation::Single(      // proxy_rules
162        "www.google.com:99",  // single
163        ""),                  // bypass rules
164  },
165
166  {
167    TEST_DESC("Tolerate a scheme"),
168
169    true,   // is_valid
170    false,  // test_read_write_access
171
172    { // Input.
173      MK_MODE(SINGLE_PROXY),       // mode
174      NULL,                        // pac_url
175      "http://www.google.com:99",  // single_uri
176    },
177
178    // Expected result.
179    false,                                   // auto_detect
180    GURL(),                                  // pac_url
181    net::ProxyRulesExpectation::Single(      // proxy_rules
182        "www.google.com:99",  // single proxy
183        ""),                  // bypass rules
184  },
185
186  {
187    TEST_DESC("Per-scheme proxy rules"),
188
189    true,  // is_valid
190    true,  // test_read_write_access
191
192    { // Input.
193      MK_MODE(PROXY_PER_SCHEME),  // mode
194      NULL,                       // pac_url
195      NULL,                       // single_uri
196      "www.google.com:80",        // http_uri
197      "www.foo.com:110",          // https_uri
198      "ftp.foo.com:121",          // ftp_uri
199      "socks.com:888",            // socks_uri
200    },
201
202    // Expected result.
203    false,                          // auto_detect
204    GURL(),                         // pac_url
205    net::ProxyRulesExpectation::PerSchemeWithSocks(  // proxy_rules
206        "www.google.com:80",        // http
207        "https://www.foo.com:110",  // https
208        "ftp.foo.com:121",          // ftp
209        "socks5://socks.com:888",   // fallback proxy
210        ""),                        // bypass rules
211  },
212
213  {
214    TEST_DESC("Bypass rules"),
215
216    true,  // is_valid
217    true,  // test_read_write_access
218
219    { // Input.
220      MK_MODE(SINGLE_PROXY),      // mode
221      NULL,                       // pac_url
222      "www.google.com",           // single_uri
223      NULL, NULL, NULL, NULL,     // per-proto
224      ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8",  // bypass_rules
225    },
226
227    // Expected result.
228    false,                          // auto_detect
229    GURL(),                         // pac_url
230    net::ProxyRulesExpectation::Single(                      // proxy_rules
231        "www.google.com:80",                                 // single proxy
232        "*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"),  // bypass_rules
233  },
234};  // tests
235
236}  // namespace
237
238class ProxyConfigServiceImplTest : public PlatformTest {
239 protected:
240  ProxyConfigServiceImplTest()
241      : ui_thread_(BrowserThread::UI, &message_loop_),
242        io_thread_(BrowserThread::IO, &message_loop_) {
243  }
244
245  virtual ~ProxyConfigServiceImplTest() {
246    config_service_ = NULL;
247    MessageLoop::current()->RunAllPending();
248  }
249
250  void CreateConfigService(
251      const ProxyConfigServiceImpl::ProxyConfig& init_config) {
252    // Instantiate proxy config service with |init_config|.
253    config_service_ = new ProxyConfigServiceImpl(init_config);
254  }
255
256  void SetAutomaticProxy(
257      ProxyConfigServiceImpl::ProxyConfig::Mode mode,
258      ProxyConfigServiceImpl::ProxyConfig::Source source,
259      const char* pac_url,
260      ProxyConfigServiceImpl::ProxyConfig* config,
261      ProxyConfigServiceImpl::ProxyConfig::AutomaticProxy* automatic_proxy) {
262    config->mode = mode;
263    automatic_proxy->source = source;
264    if (pac_url)
265      automatic_proxy->pac_url = GURL(pac_url);
266  }
267
268  void SetManualProxy(
269      ProxyConfigServiceImpl::ProxyConfig::Mode mode,
270      ProxyConfigServiceImpl::ProxyConfig::Source source,
271      const char* server_uri,
272      net::ProxyServer::Scheme scheme,
273      ProxyConfigServiceImpl::ProxyConfig* config,
274      ProxyConfigServiceImpl::ProxyConfig::ManualProxy* manual_proxy) {
275    if (!server_uri)
276      return;
277    config->mode = mode;
278    manual_proxy->source = source;
279    manual_proxy->server = net::ProxyServer::FromURI(server_uri, scheme);
280  }
281
282  void InitConfigWithTestInput(
283      const Input& input, ProxyConfigServiceImpl::ProxyConfig::Source source,
284      ProxyConfigServiceImpl::ProxyConfig* init_config) {
285    switch (input.mode) {
286      case MK_MODE(DIRECT):
287      case MK_MODE(AUTO_DETECT):
288      case MK_MODE(PAC_SCRIPT):
289        SetAutomaticProxy(input.mode, source, input.pac_url, init_config,
290                          &init_config->automatic_proxy);
291        return;
292      case MK_MODE(SINGLE_PROXY):
293        SetManualProxy(input.mode, source, input.single_uri, MK_SCHM(HTTP),
294                       init_config, &init_config->single_proxy);
295        break;
296      case MK_MODE(PROXY_PER_SCHEME):
297        SetManualProxy(input.mode, source, input.http_uri, MK_SCHM(HTTP),
298                       init_config, &init_config->http_proxy);
299        SetManualProxy(input.mode, source, input.https_uri, MK_SCHM(HTTPS),
300                       init_config, &init_config->https_proxy);
301        SetManualProxy(input.mode, source, input.ftp_uri, MK_SCHM(HTTP),
302                       init_config, &init_config->ftp_proxy);
303        SetManualProxy(input.mode, source, input.socks_uri, MK_SCHM(SOCKS5),
304                       init_config, &init_config->socks_proxy);
305        break;
306    }
307    if (input.bypass_rules) {
308      init_config->bypass_rules.ParseFromStringUsingSuffixMatching(
309          input.bypass_rules);
310    }
311  }
312
313  void TestReadWriteAccessForMode(const Input& input,
314      ProxyConfigServiceImpl::ProxyConfig::Source source) {
315    // Init config from |source|.
316    ProxyConfigServiceImpl::ProxyConfig init_config;
317    InitConfigWithTestInput(input, source, &init_config);
318    CreateConfigService(init_config);
319
320    ProxyConfigServiceImpl::ProxyConfig config;
321    config_service()->UIGetProxyConfig(&config);
322
323    // For owner, write access to config should be equal CanBeWrittenByOwner().
324    // For non-owner, config is never writeable.
325    bool expected_writeable_by_owner = CanBeWrittenByOwner(source);
326    if (config.mode == MK_MODE(PROXY_PER_SCHEME)) {
327      if (input.http_uri) {
328        EXPECT_EQ(expected_writeable_by_owner,
329                  config.CanBeWrittenByUser(true, "http"));
330        EXPECT_FALSE(config.CanBeWrittenByUser(false, "http"));
331      }
332      if (input.https_uri) {
333        EXPECT_EQ(expected_writeable_by_owner,
334                  config.CanBeWrittenByUser(true, "http"));
335        EXPECT_FALSE(config.CanBeWrittenByUser(false, "https"));
336      }
337      if (input.ftp_uri) {
338        EXPECT_EQ(expected_writeable_by_owner,
339                  config.CanBeWrittenByUser(true, "http"));
340        EXPECT_FALSE(config.CanBeWrittenByUser(false, "ftp"));
341      }
342      if (input.socks_uri) {
343        EXPECT_EQ(expected_writeable_by_owner,
344                  config.CanBeWrittenByUser(true, "http"));
345        EXPECT_FALSE(config.CanBeWrittenByUser(false, "socks"));
346      }
347    } else {
348      EXPECT_EQ(expected_writeable_by_owner,
349                config.CanBeWrittenByUser(true, std::string()));
350      EXPECT_FALSE(config.CanBeWrittenByUser(false, std::string()));
351    }
352  }
353
354  void TestReadWriteAccessForScheme(
355      ProxyConfigServiceImpl::ProxyConfig::Source source,
356      const char* server_uri,
357      const std::string& scheme) {
358    // Init with manual |scheme| proxy.
359    ProxyConfigServiceImpl::ProxyConfig init_config;
360    ProxyConfigServiceImpl::ProxyConfig::ManualProxy* proxy =
361        init_config.MapSchemeToProxy(scheme);
362    net::ProxyServer::Scheme net_scheme = MK_SCHM(HTTP);
363    if (scheme == "http" || scheme == "ftp")
364      net_scheme = MK_SCHM(HTTP);
365    else if (scheme == "https")
366      net_scheme = MK_SCHM(HTTPS);
367    else if (scheme == "socks")
368      net_scheme = MK_SCHM(SOCKS4);
369    SetManualProxy(MK_MODE(PROXY_PER_SCHEME), source, server_uri, net_scheme,
370                   &init_config, proxy);
371    CreateConfigService(init_config);
372
373    ProxyConfigServiceImpl::ProxyConfig config;
374    config_service()->UIGetProxyConfig(&config);
375
376    // For owner, write access to config should be equal CanBeWrittenByOwner().
377    // For non-owner, config is never writeable.
378    bool expected_writeable_by_owner = CanBeWrittenByOwner(source);
379    EXPECT_EQ(expected_writeable_by_owner,
380              config.CanBeWrittenByUser(true, scheme));
381    EXPECT_FALSE(config.CanBeWrittenByUser(false, scheme));
382
383    const char* all_schemes[] = {
384      "http", "https", "ftp", "socks",
385    };
386
387    // Rest of protos should be writeable by owner, but not writeable by
388    // non-owner.
389    for (size_t i = 0; i < ARRAYSIZE_UNSAFE(all_schemes); ++i) {
390      if (scheme == all_schemes[i])
391        continue;
392      EXPECT_TRUE(config.CanBeWrittenByUser(true, all_schemes[i]));
393      EXPECT_FALSE(config.CanBeWrittenByUser(false, all_schemes[i]));
394    }
395  }
396
397  // Synchronously gets the latest proxy config.
398  bool SyncGetLatestProxyConfig(net::ProxyConfig* config) {
399    // Let message loop process all messages.
400    MessageLoop::current()->RunAllPending();
401    // Calls IOGetProxyConfig (which is called from
402    // ProxyConfigService::GetLatestProxyConfig), running on faked IO thread.
403    return config_service_->IOGetProxyConfig(config);
404  }
405
406  ProxyConfigServiceImpl* config_service() const {
407    return config_service_;
408  }
409
410 private:
411  bool CanBeWrittenByOwner(
412    ProxyConfigServiceImpl::ProxyConfig::Source source) const {
413    return source == MK_SRC(POLICY) ? false : true;
414  }
415
416  ScopedStubCrosEnabler stub_cros_enabler_;
417  MessageLoop message_loop_;
418  BrowserThread ui_thread_;
419  BrowserThread io_thread_;
420
421  scoped_refptr<ProxyConfigServiceImpl> config_service_;
422};
423
424TEST_F(ProxyConfigServiceImplTest, ChromeosProxyConfigToNetProxyConfig) {
425  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
426    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
427                              tests[i].description.c_str()));
428
429    ProxyConfigServiceImpl::ProxyConfig init_config;
430    InitConfigWithTestInput(tests[i].input, MK_SRC(OWNER), &init_config);
431    CreateConfigService(init_config);
432
433    net::ProxyConfig config;
434    SyncGetLatestProxyConfig(&config);
435
436    EXPECT_EQ(tests[i].auto_detect, config.auto_detect());
437    EXPECT_EQ(tests[i].pac_url, config.pac_url());
438    EXPECT_TRUE(tests[i].proxy_rules.Matches(config.proxy_rules()));
439  }
440}
441
442TEST_F(ProxyConfigServiceImplTest, ModifyFromUI) {
443  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
444    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
445                              tests[i].description.c_str()));
446
447    // Init with direct.
448    ProxyConfigServiceImpl::ProxyConfig init_config;
449    SetAutomaticProxy(MK_MODE(DIRECT), MK_SRC(OWNER), NULL, &init_config,
450                      &init_config.automatic_proxy);
451    CreateConfigService(init_config);
452
453    // Set config to tests[i].input via UI.
454    net::ProxyBypassRules bypass_rules;
455    const Input& input = tests[i].input;
456    switch (input.mode) {
457      case MK_MODE(DIRECT) :
458        config_service()->UISetProxyConfigToDirect();
459        break;
460      case MK_MODE(AUTO_DETECT) :
461        config_service()->UISetProxyConfigToAutoDetect();
462        break;
463      case MK_MODE(PAC_SCRIPT) :
464        config_service()->UISetProxyConfigToPACScript(GURL(input.pac_url));
465        break;
466      case MK_MODE(SINGLE_PROXY) :
467        config_service()->UISetProxyConfigToSingleProxy(
468            net::ProxyServer::FromURI(input.single_uri, MK_SCHM(HTTP)));
469        if (input.bypass_rules) {
470          bypass_rules.ParseFromStringUsingSuffixMatching(input.bypass_rules);
471          config_service()->UISetProxyConfigBypassRules(bypass_rules);
472        }
473        break;
474      case MK_MODE(PROXY_PER_SCHEME) :
475        if (input.http_uri) {
476          config_service()->UISetProxyConfigToProxyPerScheme("http",
477                  net::ProxyServer::FromURI(input.http_uri, MK_SCHM(HTTP)));
478        }
479        if (input.https_uri) {
480          config_service()->UISetProxyConfigToProxyPerScheme("https",
481              net::ProxyServer::FromURI(input.https_uri, MK_SCHM(HTTPS)));
482        }
483        if (input.ftp_uri) {
484          config_service()->UISetProxyConfigToProxyPerScheme("ftp",
485              net::ProxyServer::FromURI(input.ftp_uri, MK_SCHM(HTTP)));
486        }
487        if (input.socks_uri) {
488          config_service()->UISetProxyConfigToProxyPerScheme("socks",
489              net::ProxyServer::FromURI(input.socks_uri, MK_SCHM(SOCKS5)));
490        }
491        if (input.bypass_rules) {
492          bypass_rules.ParseFromStringUsingSuffixMatching(input.bypass_rules);
493          config_service()->UISetProxyConfigBypassRules(bypass_rules);
494        }
495        break;
496    }
497
498    // Retrieve config from IO thread.
499    net::ProxyConfig io_config;
500    SyncGetLatestProxyConfig(&io_config);
501    EXPECT_EQ(tests[i].auto_detect, io_config.auto_detect());
502    EXPECT_EQ(tests[i].pac_url, io_config.pac_url());
503    EXPECT_TRUE(tests[i].proxy_rules.Matches(io_config.proxy_rules()));
504
505    // Retrieve config from UI thread.
506    ProxyConfigServiceImpl::ProxyConfig ui_config;
507    config_service()->UIGetProxyConfig(&ui_config);
508    EXPECT_EQ(input.mode, ui_config.mode);
509    if (tests[i].is_valid) {
510      if (input.pac_url)
511        EXPECT_EQ(GURL(input.pac_url), ui_config.automatic_proxy.pac_url);
512      const net::ProxyRulesExpectation& proxy_rules = tests[i].proxy_rules;
513      if (input.single_uri)
514        EXPECT_EQ(proxy_rules.single_proxy,
515                  ui_config.single_proxy.server.ToURI());
516      if (input.http_uri)
517        EXPECT_EQ(proxy_rules.proxy_for_http,
518                  ui_config.http_proxy.server.ToURI());
519      if (input.https_uri)
520        EXPECT_EQ(proxy_rules.proxy_for_https,
521                  ui_config.https_proxy.server.ToURI());
522      if (input.ftp_uri)
523        EXPECT_EQ(proxy_rules.proxy_for_ftp,
524                  ui_config.ftp_proxy.server.ToURI());
525      if (input.socks_uri) {
526        EXPECT_EQ(proxy_rules.fallback_proxy,
527                  ui_config.socks_proxy.server.ToURI());
528      }
529      if (input.bypass_rules)
530        EXPECT_TRUE(bypass_rules.Equals(ui_config.bypass_rules));
531    }
532  }
533}
534
535TEST_F(ProxyConfigServiceImplTest, ProxyChangedObserver) {
536  // This is used to observe for OnProxyConfigChanged notification.
537  class ProxyChangedObserver : public net::ProxyConfigService::Observer {
538   public:
539    explicit ProxyChangedObserver(
540        const scoped_refptr<ProxyConfigServiceImpl>& config_service)
541        : config_service_(config_service) {
542      config_service_->AddObserver(this);
543    }
544    virtual ~ProxyChangedObserver() {
545      config_service_->RemoveObserver(this);
546    }
547    net::ProxyConfigService::ConfigAvailability availability() const {
548      return availability_;
549    }
550    const net::ProxyConfig& config() const {
551      return config_;
552    }
553
554   private:
555    virtual void OnProxyConfigChanged(
556        const net::ProxyConfig& config,
557        net::ProxyConfigService::ConfigAvailability availability) {
558      config_ = config;
559      availability_ = availability;
560    }
561
562    scoped_refptr<ProxyConfigServiceImpl> config_service_;
563    net::ProxyConfigService::ConfigAvailability availability_;
564    net::ProxyConfig config_;
565  };
566
567  // Init with direct.
568  ProxyConfigServiceImpl::ProxyConfig init_config;
569  SetAutomaticProxy(MK_MODE(DIRECT), MK_SRC(OWNER), NULL, &init_config,
570                    &init_config.automatic_proxy);
571  CreateConfigService(init_config);
572
573  ProxyChangedObserver observer(config_service());
574
575  // Set to pac script from UI.
576  EXPECT_TRUE(config_service()->UISetProxyConfigToPACScript(
577      GURL("http://wpad.dat")));
578  // Retrieve config from IO thread.
579  net::ProxyConfig io_config;
580  SyncGetLatestProxyConfig(&io_config);
581
582  // Observer should have gotten the same new proxy config.
583  EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, observer.availability());
584  EXPECT_TRUE(io_config.Equals(observer.config()));
585}
586
587TEST_F(ProxyConfigServiceImplTest, SerializeAndDeserialize) {
588  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
589    if (!tests[i].is_valid)
590      continue;
591
592    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
593                              tests[i].description.c_str()));
594
595    ProxyConfigServiceImpl::ProxyConfig source_config;
596    InitConfigWithTestInput(tests[i].input, MK_SRC(OWNER), &source_config);
597
598    // Serialize source_config into std::string.
599    std::string serialized_value;
600    EXPECT_TRUE(source_config.Serialize(&serialized_value));
601
602    // Deserialize std:string into target_config.
603    ProxyConfigServiceImpl::ProxyConfig target_config;
604    EXPECT_TRUE(target_config.Deserialize(serialized_value));
605
606    // Compare the configs after serialization and deserialization.
607    net::ProxyConfig net_src_cfg;
608    net::ProxyConfig net_tgt_cfg;
609    source_config.ToNetProxyConfig(&net_src_cfg);
610    target_config.ToNetProxyConfig(&net_tgt_cfg);
611#if !defined(NDEBUG)
612    if (!net_src_cfg.Equals(net_tgt_cfg)) {
613      std::string src_output, tgt_output;
614      JSONStringValueSerializer src_serializer(&src_output);
615      src_serializer.Serialize(*net_src_cfg.ToValue());
616      JSONStringValueSerializer tgt_serializer(&tgt_output);
617      tgt_serializer.Serialize(*net_tgt_cfg.ToValue());
618      VLOG(1) << "source:\n" << src_output
619              << "\ntarget:\n" << tgt_output;
620    }
621#endif  // !defined(NDEBUG)
622    EXPECT_TRUE(net_src_cfg.Equals(net_tgt_cfg));
623  }
624}
625
626TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForPolicySource) {
627  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
628    if (!tests[i].test_read_write_access)
629      continue;
630    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
631                              tests[i].description.c_str()));
632    TestReadWriteAccessForMode(tests[i].input, MK_SRC(POLICY));
633  }
634}
635
636TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForOwnerSource) {
637  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
638    if (!tests[i].test_read_write_access)
639      continue;
640    SCOPED_TRACE(StringPrintf("Test[%" PRIuS "] %s", i,
641                              tests[i].description.c_str()));
642    TestReadWriteAccessForMode(tests[i].input, MK_SRC(OWNER));
643  }
644}
645
646TEST_F(ProxyConfigServiceImplTest, ReadWriteAccessForMixedSchemes) {
647  const char* http_uri = "www.google.com:80";
648  const char* https_uri = "www.foo.com:110";
649  const char* ftp_uri = "ftp.foo.com:121";
650  const char* socks_uri = "socks.com:888";
651
652  // Init with policy source.
653  TestReadWriteAccessForScheme(MK_SRC(POLICY), http_uri, "http");
654  TestReadWriteAccessForScheme(MK_SRC(POLICY), https_uri, "https");
655  TestReadWriteAccessForScheme(MK_SRC(POLICY), ftp_uri, "ftp");
656  TestReadWriteAccessForScheme(MK_SRC(POLICY), socks_uri, "socks");
657
658  // Init with owner source.
659  TestReadWriteAccessForScheme(MK_SRC(OWNER), http_uri, "http");
660  TestReadWriteAccessForScheme(MK_SRC(OWNER), https_uri, "https");
661  TestReadWriteAccessForScheme(MK_SRC(OWNER), ftp_uri, "ftp");
662  TestReadWriteAccessForScheme(MK_SRC(OWNER), socks_uri, "socks");
663}
664
665}  // namespace chromeos
666