proxy_config_unittest.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  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. #include "net/proxy_resolution/proxy_config.h"
  5. #include "base/json/json_writer.h"
  6. #include "base/values.h"
  7. #include "net/base/proxy_string_util.h"
  8. #include "net/proxy_resolution/proxy_config_service_common_unittest.h"
  9. #include "net/proxy_resolution/proxy_info.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace net {
  12. namespace {
  13. void ExpectProxyServerEquals(const char* expectation,
  14. const ProxyList& proxy_servers) {
  15. if (expectation == nullptr) {
  16. EXPECT_TRUE(proxy_servers.IsEmpty());
  17. } else {
  18. EXPECT_EQ(expectation, proxy_servers.ToPacString());
  19. }
  20. }
  21. TEST(ProxyConfigTest, Equals) {
  22. // Test |ProxyConfig::auto_detect|.
  23. ProxyConfig config1;
  24. config1.set_auto_detect(true);
  25. ProxyConfig config2;
  26. config2.set_auto_detect(false);
  27. EXPECT_FALSE(config1.Equals(config2));
  28. EXPECT_FALSE(config2.Equals(config1));
  29. config2.set_auto_detect(true);
  30. EXPECT_TRUE(config1.Equals(config2));
  31. EXPECT_TRUE(config2.Equals(config1));
  32. // Test |ProxyConfig::pac_url|.
  33. config2.set_pac_url(GURL("http://wpad/wpad.dat"));
  34. EXPECT_FALSE(config1.Equals(config2));
  35. EXPECT_FALSE(config2.Equals(config1));
  36. config1.set_pac_url(GURL("http://wpad/wpad.dat"));
  37. EXPECT_TRUE(config1.Equals(config2));
  38. EXPECT_TRUE(config2.Equals(config1));
  39. // Test |ProxyConfig::proxy_rules|.
  40. config2.proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST;
  41. config2.proxy_rules().single_proxies.SetSingleProxyServer(
  42. ProxyUriToProxyServer("myproxy:80", ProxyServer::SCHEME_HTTP));
  43. EXPECT_FALSE(config1.Equals(config2));
  44. EXPECT_FALSE(config2.Equals(config1));
  45. config1.proxy_rules().type = ProxyConfig::ProxyRules::Type::PROXY_LIST;
  46. config1.proxy_rules().single_proxies.SetSingleProxyServer(
  47. ProxyUriToProxyServer("myproxy:100", ProxyServer::SCHEME_HTTP));
  48. EXPECT_FALSE(config1.Equals(config2));
  49. EXPECT_FALSE(config2.Equals(config1));
  50. config1.proxy_rules().single_proxies.SetSingleProxyServer(
  51. ProxyUriToProxyServer("myproxy", ProxyServer::SCHEME_HTTP));
  52. EXPECT_TRUE(config1.Equals(config2));
  53. EXPECT_TRUE(config2.Equals(config1));
  54. // Test |ProxyConfig::bypass_rules|.
  55. config2.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
  56. EXPECT_FALSE(config1.Equals(config2));
  57. EXPECT_FALSE(config2.Equals(config1));
  58. config1.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
  59. EXPECT_TRUE(config1.Equals(config2));
  60. EXPECT_TRUE(config2.Equals(config1));
  61. // Test |ProxyConfig::proxy_rules.reverse_bypass|.
  62. config2.proxy_rules().reverse_bypass = true;
  63. EXPECT_FALSE(config1.Equals(config2));
  64. EXPECT_FALSE(config2.Equals(config1));
  65. config1.proxy_rules().reverse_bypass = true;
  66. EXPECT_TRUE(config1.Equals(config2));
  67. EXPECT_TRUE(config2.Equals(config1));
  68. }
  69. struct ProxyConfigToValueTestCase {
  70. ProxyConfig config;
  71. const char* expected_value_json;
  72. };
  73. class ProxyConfigToValueTest
  74. : public ::testing::TestWithParam<ProxyConfigToValueTestCase> {};
  75. TEST_P(ProxyConfigToValueTest, ToValueJSON) {
  76. const ProxyConfigToValueTestCase& test_case = GetParam();
  77. base::Value value = test_case.config.ToValue();
  78. std::string json_string;
  79. ASSERT_TRUE(base::JSONWriter::Write(value, &json_string));
  80. EXPECT_EQ(std::string(test_case.expected_value_json), json_string);
  81. }
  82. ProxyConfigToValueTestCase GetTestCaseDirect() {
  83. return {ProxyConfig::CreateDirect(), "{}"};
  84. }
  85. ProxyConfigToValueTestCase GetTestCaseAutoDetect() {
  86. return {ProxyConfig::CreateAutoDetect(), "{\"auto_detect\":true}"};
  87. }
  88. ProxyConfigToValueTestCase GetTestCasePacUrl() {
  89. ProxyConfig config;
  90. config.set_pac_url(GURL("http://www.example.com/test.pac"));
  91. return {std::move(config),
  92. "{\"pac_url\":\"http://www.example.com/test.pac\"}"};
  93. }
  94. ProxyConfigToValueTestCase GetTestCasePacUrlMandatory() {
  95. ProxyConfig config;
  96. config.set_pac_url(GURL("http://www.example.com/test.pac"));
  97. config.set_pac_mandatory(true);
  98. return {std::move(config),
  99. "{\"pac_mandatory\":true,\"pac_url\":\"http://www.example.com/"
  100. "test.pac\"}"};
  101. }
  102. ProxyConfigToValueTestCase GetTestCasePacUrlAndAutoDetect() {
  103. ProxyConfig config = ProxyConfig::CreateAutoDetect();
  104. config.set_pac_url(GURL("http://www.example.com/test.pac"));
  105. return {
  106. std::move(config),
  107. "{\"auto_detect\":true,\"pac_url\":\"http://www.example.com/test.pac\"}"};
  108. }
  109. ProxyConfigToValueTestCase GetTestCaseSingleProxy() {
  110. ProxyConfig config;
  111. config.proxy_rules().ParseFromString("https://proxy1:8080");
  112. return {std::move(config), "{\"single_proxy\":[\"https://proxy1:8080\"]}"};
  113. }
  114. ProxyConfigToValueTestCase GetTestCaseSingleProxyWithBypass() {
  115. ProxyConfig config;
  116. config.proxy_rules().ParseFromString("https://proxy1:8080");
  117. config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
  118. config.proxy_rules().bypass_rules.AddRuleFromString("192.168.0.1/16");
  119. return {std::move(config),
  120. "{\"bypass_list\":[\"*.google.com\",\"192.168.0.1/"
  121. "16\"],\"single_proxy\":[\"https://proxy1:8080\"]}"};
  122. }
  123. ProxyConfigToValueTestCase GetTestCaseSingleProxyWithReversedBypass() {
  124. ProxyConfig config;
  125. config.proxy_rules().ParseFromString("https://proxy1:8080");
  126. config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
  127. config.proxy_rules().reverse_bypass = true;
  128. return {std::move(config),
  129. "{\"bypass_list\":[\"*.google.com\"],\"reverse_bypass\":true,"
  130. "\"single_proxy\":[\"https://proxy1:8080\"]}"};
  131. }
  132. ProxyConfigToValueTestCase GetTestCaseProxyPerScheme() {
  133. ProxyConfig config;
  134. config.proxy_rules().ParseFromString(
  135. "http=https://proxy1:8080;https=socks5://proxy2");
  136. config.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
  137. config.set_pac_url(GURL("http://wpad/wpad.dat"));
  138. config.set_auto_detect(true);
  139. return {
  140. std::move(config),
  141. "{\"auto_detect\":true,\"bypass_list\":[\"*.google.com\"],\"pac_url\":"
  142. "\"http://wpad/wpad.dat\",\"proxy_per_scheme\":{\"http\":[\"https://"
  143. "proxy1:8080\"],\"https\":[\"socks5://proxy2:1080\"]}}"};
  144. }
  145. ProxyConfigToValueTestCase GetTestCaseSingleProxyList() {
  146. ProxyConfig config;
  147. config.proxy_rules().ParseFromString(
  148. "https://proxy1:8080,http://proxy2,direct://");
  149. return {std::move(config),
  150. "{\"single_proxy\":[\"https://proxy1:8080\",\"proxy2:80\",\"direct://"
  151. "\"]}"};
  152. }
  153. INSTANTIATE_TEST_SUITE_P(
  154. All,
  155. ProxyConfigToValueTest,
  156. testing::Values(GetTestCaseDirect(),
  157. GetTestCaseAutoDetect(),
  158. GetTestCasePacUrl(),
  159. GetTestCasePacUrlMandatory(),
  160. GetTestCasePacUrlAndAutoDetect(),
  161. GetTestCaseSingleProxy(),
  162. GetTestCaseSingleProxyWithBypass(),
  163. GetTestCaseSingleProxyWithReversedBypass(),
  164. GetTestCaseProxyPerScheme(),
  165. GetTestCaseSingleProxyList()));
  166. TEST(ProxyConfigTest, ParseProxyRules) {
  167. const struct {
  168. const char* proxy_rules;
  169. ProxyConfig::ProxyRules::Type type;
  170. // These will be PAC-stle strings, eg 'PROXY foo.com'
  171. const char* single_proxy;
  172. const char* proxy_for_http;
  173. const char* proxy_for_https;
  174. const char* proxy_for_ftp;
  175. const char* fallback_proxy;
  176. } tests[] = {
  177. // One HTTP proxy for all schemes.
  178. {
  179. "myproxy:80",
  180. ProxyConfig::ProxyRules::Type::PROXY_LIST,
  181. "PROXY myproxy:80",
  182. nullptr,
  183. nullptr,
  184. nullptr,
  185. nullptr,
  186. },
  187. // Multiple HTTP proxies for all schemes.
  188. {
  189. "myproxy:80,https://myotherproxy",
  190. ProxyConfig::ProxyRules::Type::PROXY_LIST,
  191. "PROXY myproxy:80;HTTPS myotherproxy:443",
  192. nullptr,
  193. nullptr,
  194. nullptr,
  195. nullptr,
  196. },
  197. // Only specify a proxy server for "http://" urls.
  198. {
  199. "http=myproxy:80",
  200. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  201. nullptr,
  202. "PROXY myproxy:80",
  203. nullptr,
  204. nullptr,
  205. nullptr,
  206. },
  207. // Specify an HTTP proxy for "ftp://" and a SOCKS proxy for "https://"
  208. // urls.
  209. {
  210. "ftp=ftp-proxy ; https=socks4://foopy",
  211. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  212. nullptr,
  213. nullptr,
  214. "SOCKS foopy:1080",
  215. "PROXY ftp-proxy:80",
  216. nullptr,
  217. },
  218. // Give a scheme-specific proxy as well as a non-scheme specific.
  219. // The first entry "foopy" takes precedance marking this list as
  220. // Type::PROXY_LIST.
  221. {
  222. "foopy ; ftp=ftp-proxy",
  223. ProxyConfig::ProxyRules::Type::PROXY_LIST,
  224. "PROXY foopy:80",
  225. nullptr,
  226. nullptr,
  227. nullptr,
  228. nullptr,
  229. },
  230. // Give a scheme-specific proxy as well as a non-scheme specific.
  231. // The first entry "ftp=ftp-proxy" takes precedance marking this list as
  232. // Type::PROXY_LIST_PER_SCHEME.
  233. {
  234. "ftp=ftp-proxy ; foopy",
  235. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  236. nullptr,
  237. nullptr,
  238. nullptr,
  239. "PROXY ftp-proxy:80",
  240. nullptr,
  241. },
  242. // Include a list of entries for a single scheme.
  243. {
  244. "ftp=ftp1,ftp2,ftp3",
  245. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  246. nullptr,
  247. nullptr,
  248. nullptr,
  249. "PROXY ftp1:80;PROXY ftp2:80;PROXY ftp3:80",
  250. nullptr,
  251. },
  252. // Include multiple entries for the same scheme -- they accumulate.
  253. {
  254. "http=http1,http2; http=http3",
  255. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  256. nullptr,
  257. "PROXY http1:80;PROXY http2:80;PROXY http3:80",
  258. nullptr,
  259. nullptr,
  260. nullptr,
  261. },
  262. // Include lists of entries for multiple schemes.
  263. {
  264. "ftp=ftp1,ftp2,ftp3 ; http=http1,http2; ",
  265. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  266. nullptr,
  267. "PROXY http1:80;PROXY http2:80",
  268. nullptr,
  269. "PROXY ftp1:80;PROXY ftp2:80;PROXY ftp3:80",
  270. nullptr,
  271. },
  272. // Include non-default proxy schemes.
  273. {
  274. "http=https://secure_proxy; ftp=socks4://socks_proxy; "
  275. "https=socks://foo",
  276. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  277. nullptr,
  278. "HTTPS secure_proxy:443",
  279. "SOCKS5 foo:1080",
  280. "SOCKS socks_proxy:1080",
  281. nullptr,
  282. },
  283. // Only SOCKS proxy present, others being blank.
  284. {
  285. "socks=foopy",
  286. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  287. nullptr,
  288. nullptr,
  289. nullptr,
  290. nullptr,
  291. "SOCKS foopy:1080",
  292. },
  293. // SOCKS proxy present along with other proxies too
  294. {
  295. "http=httpproxy ; https=httpsproxy ; ftp=ftpproxy ; socks=foopy ",
  296. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  297. nullptr,
  298. "PROXY httpproxy:80",
  299. "PROXY httpsproxy:80",
  300. "PROXY ftpproxy:80",
  301. "SOCKS foopy:1080",
  302. },
  303. // SOCKS proxy (with modifier) present along with some proxies
  304. // (FTP being blank)
  305. {
  306. "http=httpproxy ; https=httpsproxy ; socks=socks5://foopy ",
  307. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  308. nullptr,
  309. "PROXY httpproxy:80",
  310. "PROXY httpsproxy:80",
  311. nullptr,
  312. "SOCKS5 foopy:1080",
  313. },
  314. // Include unsupported schemes -- they are discarded.
  315. {
  316. "crazy=foopy ; foo=bar ; https=myhttpsproxy",
  317. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  318. nullptr,
  319. nullptr,
  320. "PROXY myhttpsproxy:80",
  321. nullptr,
  322. nullptr,
  323. },
  324. // direct:// as first option for a scheme.
  325. {
  326. "http=direct://,myhttpproxy; https=direct://",
  327. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  328. nullptr,
  329. "DIRECT;PROXY myhttpproxy:80",
  330. "DIRECT",
  331. nullptr,
  332. nullptr,
  333. },
  334. // direct:// as a second option for a scheme.
  335. {
  336. "http=myhttpproxy,direct://",
  337. ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
  338. nullptr,
  339. "PROXY myhttpproxy:80;DIRECT",
  340. nullptr,
  341. nullptr,
  342. nullptr,
  343. },
  344. };
  345. ProxyConfig config;
  346. for (const auto& test : tests) {
  347. config.proxy_rules().ParseFromString(test.proxy_rules);
  348. EXPECT_EQ(test.type, config.proxy_rules().type);
  349. ExpectProxyServerEquals(test.single_proxy,
  350. config.proxy_rules().single_proxies);
  351. ExpectProxyServerEquals(test.proxy_for_http,
  352. config.proxy_rules().proxies_for_http);
  353. ExpectProxyServerEquals(test.proxy_for_https,
  354. config.proxy_rules().proxies_for_https);
  355. ExpectProxyServerEquals(test.proxy_for_ftp,
  356. config.proxy_rules().proxies_for_ftp);
  357. ExpectProxyServerEquals(test.fallback_proxy,
  358. config.proxy_rules().fallback_proxies);
  359. }
  360. }
  361. TEST(ProxyConfigTest, ProxyRulesSetBypassFlag) {
  362. // Test whether the did_bypass_proxy() flag is set in proxy info correctly.
  363. ProxyConfig::ProxyRules rules;
  364. ProxyInfo result;
  365. rules.ParseFromString("http=httpproxy:80");
  366. rules.bypass_rules.AddRuleFromString(".com");
  367. rules.Apply(GURL("http://example.com"), &result);
  368. EXPECT_TRUE(result.is_direct_only());
  369. EXPECT_TRUE(result.did_bypass_proxy());
  370. rules.Apply(GURL("http://example.org"), &result);
  371. EXPECT_FALSE(result.is_direct());
  372. EXPECT_FALSE(result.did_bypass_proxy());
  373. // Try with reversed bypass rules.
  374. rules.reverse_bypass = true;
  375. rules.Apply(GURL("http://example.org"), &result);
  376. EXPECT_TRUE(result.is_direct_only());
  377. EXPECT_TRUE(result.did_bypass_proxy());
  378. rules.Apply(GURL("http://example.com"), &result);
  379. EXPECT_FALSE(result.is_direct());
  380. EXPECT_FALSE(result.did_bypass_proxy());
  381. }
  382. static const char kWsUrl[] = "ws://example.com/echo";
  383. static const char kWssUrl[] = "wss://example.com/echo";
  384. class ProxyConfigWebSocketTest : public ::testing::Test {
  385. protected:
  386. void ParseFromString(const std::string& rules) {
  387. rules_.ParseFromString(rules);
  388. }
  389. void Apply(const GURL& gurl) { rules_.Apply(gurl, &info_); }
  390. std::string ToPacString() const { return info_.ToPacString(); }
  391. static GURL WsUrl() { return GURL(kWsUrl); }
  392. static GURL WssUrl() { return GURL(kWssUrl); }
  393. ProxyConfig::ProxyRules rules_;
  394. ProxyInfo info_;
  395. };
  396. // If a single proxy is set for all protocols, WebSocket uses it.
  397. TEST_F(ProxyConfigWebSocketTest, UsesProxy) {
  398. ParseFromString("proxy:3128");
  399. Apply(WsUrl());
  400. EXPECT_EQ("PROXY proxy:3128", ToPacString());
  401. }
  402. // See RFC6455 Section 4.1. item 3, "_Proxy Usage_". Note that this favors a
  403. // SOCKSv4 proxy (although technically the spec only notes SOCKSv5).
  404. TEST_F(ProxyConfigWebSocketTest, PrefersSocksV4) {
  405. ParseFromString(
  406. "http=proxy:3128 ; https=sslproxy:3128 ; socks=socksproxy:1080");
  407. Apply(WsUrl());
  408. EXPECT_EQ("SOCKS socksproxy:1080", ToPacString());
  409. }
  410. // See RFC6455 Section 4.1. item 3, "_Proxy Usage_".
  411. TEST_F(ProxyConfigWebSocketTest, PrefersSocksV5) {
  412. ParseFromString(
  413. "http=proxy:3128 ; https=sslproxy:3128 ; socks=socks5://socksproxy:1080");
  414. Apply(WsUrl());
  415. EXPECT_EQ("SOCKS5 socksproxy:1080", ToPacString());
  416. }
  417. TEST_F(ProxyConfigWebSocketTest, PrefersHttpsToHttp) {
  418. ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
  419. Apply(WssUrl());
  420. EXPECT_EQ("PROXY sslproxy:3128", ToPacString());
  421. }
  422. // Tests when a proxy-per-url-scheme configuration was used, and proxies are
  423. // specified for http://, https://, and a fallback proxy (non-SOCKS).
  424. // Even though the fallback proxy is not SOCKS, it is still favored over the
  425. // proxy for http://* and https://*.
  426. TEST_F(ProxyConfigWebSocketTest, PrefersNonSocksFallbackOverHttps) {
  427. // The notation for "socks=" is abused to set the "fallback proxy".
  428. ParseFromString(
  429. "http=proxy:3128 ; https=sslproxy:3128; socks=https://httpsproxy");
  430. EXPECT_EQ("HTTPS httpsproxy:443", rules_.fallback_proxies.ToPacString());
  431. Apply(WssUrl());
  432. EXPECT_EQ("HTTPS httpsproxy:443", ToPacString());
  433. }
  434. // Tests when a proxy-per-url-scheme configuration was used, and the fallback
  435. // proxy is a non-SOCKS proxy, and no proxy was given for https://* or
  436. // http://*. The fallback proxy is used.
  437. TEST_F(ProxyConfigWebSocketTest, UsesNonSocksFallbackProxy) {
  438. // The notation for "socks=" is abused to set the "fallback proxy".
  439. ParseFromString("ftp=ftpproxy:3128; socks=https://httpsproxy");
  440. EXPECT_EQ("HTTPS httpsproxy:443", rules_.fallback_proxies.ToPacString());
  441. Apply(WssUrl());
  442. EXPECT_EQ("HTTPS httpsproxy:443", ToPacString());
  443. }
  444. TEST_F(ProxyConfigWebSocketTest, PrefersHttpsEvenForWs) {
  445. ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
  446. Apply(WsUrl());
  447. EXPECT_EQ("PROXY sslproxy:3128", ToPacString());
  448. }
  449. TEST_F(ProxyConfigWebSocketTest, PrefersHttpToDirect) {
  450. ParseFromString("http=proxy:3128");
  451. Apply(WssUrl());
  452. EXPECT_EQ("PROXY proxy:3128", ToPacString());
  453. }
  454. TEST_F(ProxyConfigWebSocketTest, IgnoresFtpProxy) {
  455. ParseFromString("ftp=ftpproxy:3128");
  456. Apply(WssUrl());
  457. EXPECT_EQ("DIRECT", ToPacString());
  458. }
  459. TEST_F(ProxyConfigWebSocketTest, ObeysBypassRules) {
  460. ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
  461. rules_.bypass_rules.AddRuleFromString(".chromium.org");
  462. Apply(GURL("wss://codereview.chromium.org/feed"));
  463. EXPECT_EQ("DIRECT", ToPacString());
  464. }
  465. TEST_F(ProxyConfigWebSocketTest, ObeysLocalBypass) {
  466. ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
  467. rules_.bypass_rules.AddRuleFromString("<local>");
  468. Apply(GURL("ws://localhost/feed"));
  469. EXPECT_EQ("DIRECT", ToPacString());
  470. }
  471. } // namespace
  472. } // namespace net