1 // Copyright (c) 2006-2008 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_list.h"
6
7 #include "net/proxy/proxy_server.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 namespace net {
11
12 namespace {
13
14 // Test parsing from a PAC string.
TEST(ProxyListTest,SetFromPacString)15 TEST(ProxyListTest, SetFromPacString) {
16 const struct {
17 const char* pac_input;
18 const char* pac_output;
19 } tests[] = {
20 // Valid inputs:
21 { "PROXY foopy:10",
22 "PROXY foopy:10",
23 },
24 { " DIRECT", // leading space.
25 "DIRECT",
26 },
27 { "PROXY foopy1 ; proxy foopy2;\t DIRECT",
28 "PROXY foopy1:80;PROXY foopy2:80;DIRECT",
29 },
30 { "proxy foopy1 ; SOCKS foopy2",
31 "PROXY foopy1:80;SOCKS foopy2:1080",
32 },
33 // Try putting DIRECT first.
34 { "DIRECT ; proxy foopy1 ; DIRECT ; SOCKS5 foopy2;DIRECT ",
35 "DIRECT;PROXY foopy1:80;DIRECT;SOCKS5 foopy2:1080;DIRECT",
36 },
37 // Try putting DIRECT consecutively.
38 { "DIRECT ; proxy foopy1:80; DIRECT ; DIRECT",
39 "DIRECT;PROXY foopy1:80;DIRECT;DIRECT",
40 },
41
42 // Invalid inputs (parts which aren't understood get
43 // silently discarded):
44 //
45 // If the proxy list string parsed to empty, automatically fall-back to
46 // DIRECT.
47 { "PROXY-foopy:10",
48 "DIRECT",
49 },
50 { "PROXY",
51 "DIRECT",
52 },
53 { "PROXY foopy1 ; JUNK ; JUNK ; SOCKS5 foopy2 ; ;",
54 "PROXY foopy1:80;SOCKS5 foopy2:1080",
55 },
56 };
57
58 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
59 ProxyList list;
60 list.SetFromPacString(tests[i].pac_input);
61 EXPECT_EQ(tests[i].pac_output, list.ToPacString());
62 EXPECT_FALSE(list.IsEmpty());
63 }
64 }
65
TEST(ProxyListTest,RemoveProxiesWithoutScheme)66 TEST(ProxyListTest, RemoveProxiesWithoutScheme) {
67 const struct {
68 const char* pac_input;
69 int filter;
70 const char* filtered_pac_output;
71 } tests[] = {
72 { "PROXY foopy:10 ; SOCKS5 foopy2 ; SOCKS foopy11 ; PROXY foopy3 ; DIRECT",
73 // Remove anything that isn't HTTP or DIRECT.
74 ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP,
75 "PROXY foopy:10;PROXY foopy3:80;DIRECT",
76 },
77 { "PROXY foopy:10 ; SOCKS5 foopy2",
78 // Remove anything that isn't HTTP or SOCKS5.
79 ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_SOCKS4,
80 "",
81 },
82 };
83
84 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
85 ProxyList list;
86 list.SetFromPacString(tests[i].pac_input);
87 list.RemoveProxiesWithoutScheme(tests[i].filter);
88 EXPECT_EQ(tests[i].filtered_pac_output, list.ToPacString());
89 }
90 }
91
TEST(ProxyListTest,HasUntriedProxies)92 TEST(ProxyListTest, HasUntriedProxies) {
93 // As in DeprioritizeBadProxies, we use a lengthy timeout to avoid depending
94 // on the current time.
95 ProxyRetryInfo proxy_retry_info;
96 proxy_retry_info.bad_until =
97 base::TimeTicks::Now() + base::TimeDelta::FromDays(1);
98
99 // An empty list has nothing to try.
100 {
101 ProxyList list;
102 ProxyRetryInfoMap proxy_retry_info;
103 EXPECT_FALSE(list.HasUntriedProxies(proxy_retry_info));
104 }
105
106 // A list with one bad proxy has something to try. With two bad proxies,
107 // there's nothing to try.
108 {
109 ProxyList list;
110 list.SetFromPacString("PROXY bad1:80; PROXY bad2:80");
111 ProxyRetryInfoMap retry_info_map;
112 retry_info_map["bad1:80"] = proxy_retry_info;
113 EXPECT_TRUE(list.HasUntriedProxies(retry_info_map));
114 retry_info_map["bad2:80"] = proxy_retry_info;
115 EXPECT_FALSE(list.HasUntriedProxies(retry_info_map));
116 }
117
118 // A list with one bad proxy and a DIRECT entry has something to try.
119 {
120 ProxyList list;
121 list.SetFromPacString("PROXY bad1:80; DIRECT");
122 ProxyRetryInfoMap retry_info_map;
123 retry_info_map["bad1:80"] = proxy_retry_info;
124 EXPECT_TRUE(list.HasUntriedProxies(retry_info_map));
125 }
126 }
127
TEST(ProxyListTest,DeprioritizeBadProxies)128 TEST(ProxyListTest, DeprioritizeBadProxies) {
129 // Retry info that marks a proxy as being bad for a *very* long time (to avoid
130 // the test depending on the current time.)
131 ProxyRetryInfo proxy_retry_info;
132 proxy_retry_info.bad_until =
133 base::TimeTicks::Now() + base::TimeDelta::FromDays(1);
134
135 // Call DeprioritizeBadProxies with an empty map -- should have no effect.
136 {
137 ProxyList list;
138 list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
139
140 ProxyRetryInfoMap retry_info_map;
141 list.DeprioritizeBadProxies(retry_info_map);
142 EXPECT_EQ("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80",
143 list.ToPacString());
144 }
145
146 // Call DeprioritizeBadProxies with 2 of the three proxies marked as bad.
147 // These proxies should be retried last.
148 {
149 ProxyList list;
150 list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
151
152 ProxyRetryInfoMap retry_info_map;
153 retry_info_map["foopy1:80"] = proxy_retry_info;
154 retry_info_map["foopy3:80"] = proxy_retry_info;
155 retry_info_map["socks5://localhost:1080"] = proxy_retry_info;
156
157 list.DeprioritizeBadProxies(retry_info_map);
158
159 EXPECT_EQ("PROXY foopy2:80;PROXY foopy1:80;PROXY foopy3:80",
160 list.ToPacString());
161 }
162
163 // Call DeprioritizeBadProxies where ALL of the proxies are marked as bad.
164 // This should have no effect on the order.
165 {
166 ProxyList list;
167 list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
168
169 ProxyRetryInfoMap retry_info_map;
170 retry_info_map["foopy1:80"] = proxy_retry_info;
171 retry_info_map["foopy2:80"] = proxy_retry_info;
172 retry_info_map["foopy3:80"] = proxy_retry_info;
173
174 list.DeprioritizeBadProxies(retry_info_map);
175
176 EXPECT_EQ("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80",
177 list.ToPacString());
178 }
179 }
180
181 } // namesapce
182
183 } // namespace net
184