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