1 // Copyright 2023 The Chromium Authors
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/base/proxy_chain.h"
6
7 #include <optional>
8 #include <sstream>
9
10 #include "base/strings/string_number_conversions.h"
11 #include "base/test/gtest_util.h"
12 #include "net/base/proxy_server.h"
13 #include "net/base/proxy_string_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace net {
17
18 namespace {
19
TEST(ProxyChainTest,DefaultConstructor)20 TEST(ProxyChainTest, DefaultConstructor) {
21 ProxyChain proxy_chain;
22 EXPECT_FALSE(proxy_chain.IsValid());
23 }
24
TEST(ProxyChainTest,ConstructorsAndAssignmentOperators)25 TEST(ProxyChainTest, ConstructorsAndAssignmentOperators) {
26 std::vector proxy_servers = {
27 ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
28 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)};
29
30 ProxyChain proxy_chain = ProxyChain(proxy_servers);
31
32 ProxyChain copy_constructed(proxy_chain);
33 EXPECT_EQ(proxy_chain, copy_constructed);
34
35 ProxyChain copy_assigned = proxy_chain;
36 EXPECT_EQ(proxy_chain, copy_assigned);
37
38 ProxyChain move_constructed{std::move(copy_constructed)};
39 EXPECT_EQ(proxy_chain, move_constructed);
40
41 ProxyChain move_assigned = std::move(copy_assigned);
42 EXPECT_EQ(proxy_chain, move_assigned);
43 }
44
TEST(ProxyChainTest,DirectProxy)45 TEST(ProxyChainTest, DirectProxy) {
46 ProxyChain proxy_chain1 = ProxyChain::Direct();
47 ProxyChain proxy_chain2 = ProxyChain(std::vector<ProxyServer>());
48 std::vector<ProxyServer> proxy_servers = {};
49
50 // Equal and valid proxy chains.
51 ASSERT_EQ(proxy_chain1, proxy_chain2);
52 EXPECT_TRUE(proxy_chain1.IsValid());
53 EXPECT_TRUE(proxy_chain2.IsValid());
54
55 EXPECT_TRUE(proxy_chain1.is_direct());
56 EXPECT_FALSE(proxy_chain1.is_single_proxy());
57 EXPECT_FALSE(proxy_chain1.is_multi_proxy());
58 ASSERT_EQ(proxy_chain1.length(), 0u);
59 ASSERT_EQ(proxy_chain1.proxy_servers(), proxy_servers);
60 }
61
TEST(ProxyChainTest,Ostream)62 TEST(ProxyChainTest, Ostream) {
63 ProxyChain proxy_chain =
64 ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTP, "foo", 80);
65 std::ostringstream out;
66 out << proxy_chain;
67 EXPECT_EQ(out.str(), "[foo:80]");
68 }
69
TEST(ProxyChainTest,ToDebugString)70 TEST(ProxyChainTest, ToDebugString) {
71 ProxyChain proxy_chain1 =
72 ProxyChain(ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_SOCKS5));
73 EXPECT_EQ(proxy_chain1.ToDebugString(), "[socks5://foo:333]");
74
75 ProxyChain proxy_chain2 =
76 ProxyChain({ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS),
77 ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS)});
78 EXPECT_EQ(proxy_chain2.ToDebugString(), "[https://foo:444, https://foo:555]");
79
80 ProxyChain direct_proxy_chain = ProxyChain::Direct();
81 EXPECT_EQ(direct_proxy_chain.ToDebugString(), "[direct://]");
82
83 ProxyChain ip_protection_proxy_chain = ProxyChain::ForIpProtection(
84 {ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS),
85 ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS)});
86 EXPECT_EQ(ip_protection_proxy_chain.ToDebugString(),
87 "[https://foo:444, https://foo:555] (IP Protection)");
88
89 ProxyChain invalid_proxy_chain = ProxyChain();
90 EXPECT_EQ(invalid_proxy_chain.ToDebugString(), "INVALID PROXY CHAIN");
91 }
92
TEST(ProxyChainTest,FromSchemeHostAndPort)93 TEST(ProxyChainTest, FromSchemeHostAndPort) {
94 const struct {
95 const ProxyServer::Scheme input_scheme;
96 const char* const input_host;
97 const std::optional<uint16_t> input_port;
98 const char* const input_port_str;
99 const char* const expected_host;
100 const uint16_t expected_port;
101 } tests[] = {
102 {ProxyServer::SCHEME_HTTP, "foopy", 80, "80", "foopy", 80},
103
104 // Non-standard port
105 {ProxyServer::SCHEME_HTTP, "foopy", 10, "10", "foopy", 10},
106 {ProxyServer::SCHEME_HTTP, "foopy", 0, "0", "foopy", 0},
107
108 // Hostname canonicalization
109 {ProxyServer::SCHEME_HTTP, "FoOpY", 80, "80", "foopy", 80},
110 {ProxyServer::SCHEME_HTTP, "f\u00fcpy", 80, "80", "xn--fpy-hoa", 80},
111
112 // IPv4 literal
113 {ProxyServer::SCHEME_HTTP, "1.2.3.4", 80, "80", "1.2.3.4", 80},
114
115 // IPv4 literal canonicalization
116 {ProxyServer::SCHEME_HTTP, "127.1", 80, "80", "127.0.0.1", 80},
117 {ProxyServer::SCHEME_HTTP, "0x7F.0x1", 80, "80", "127.0.0.1", 80},
118 {ProxyServer::SCHEME_HTTP, "0177.01", 80, "80", "127.0.0.1", 80},
119
120 // IPv6 literal
121 {ProxyServer::SCHEME_HTTP, "[3ffe:2a00:100:7031::1]", 80, "80",
122 "[3ffe:2a00:100:7031::1]", 80},
123 {ProxyServer::SCHEME_HTTP, "3ffe:2a00:100:7031::1", 80, "80",
124 "[3ffe:2a00:100:7031::1]", 80},
125
126 // IPv6 literal canonicalization
127 {ProxyServer::SCHEME_HTTP, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80,
128 "80", "[fedc:ba98:7654:3210:fedc:ba98:7654:3210]", 80},
129 {ProxyServer::SCHEME_HTTP, "::192.9.5.5", 80, "80", "[::c009:505]", 80},
130
131 // Other schemes
132 {ProxyServer::SCHEME_HTTPS, "foopy", 111, "111", "foopy", 111},
133 {ProxyServer::SCHEME_SOCKS4, "foopy", 111, "111", "foopy", 111},
134 {ProxyServer::SCHEME_SOCKS5, "foopy", 111, "111", "foopy", 111},
135
136 // Default ports
137 {ProxyServer::SCHEME_HTTP, "foopy", std::nullopt, "", "foopy", 80},
138 {ProxyServer::SCHEME_HTTPS, "foopy", std::nullopt, "", "foopy", 443},
139 {ProxyServer::SCHEME_SOCKS4, "foopy", std::nullopt, "", "foopy", 1080},
140 {ProxyServer::SCHEME_SOCKS5, "foopy", std::nullopt, "", "foopy", 1080},
141 };
142
143 for (size_t i = 0; i < std::size(tests); ++i) {
144 SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i].input_host + ":" +
145 base::NumberToString(tests[i].input_port.value_or(-1)));
146 auto chain = ProxyChain::FromSchemeHostAndPort(
147 tests[i].input_scheme, tests[i].input_host, tests[i].input_port);
148 auto proxy = chain.First();
149
150 ASSERT_TRUE(proxy.is_valid());
151 EXPECT_EQ(proxy.scheme(), tests[i].input_scheme);
152 EXPECT_EQ(proxy.GetHost(), tests[i].expected_host);
153 EXPECT_EQ(proxy.GetPort(), tests[i].expected_port);
154
155 auto chain_from_string_port = ProxyChain::FromSchemeHostAndPort(
156 tests[i].input_scheme, tests[i].input_host, tests[i].input_port_str);
157 auto proxy_from_string_port = chain_from_string_port.First();
158 EXPECT_TRUE(proxy_from_string_port.is_valid());
159 EXPECT_EQ(proxy, proxy_from_string_port);
160 }
161 }
162
TEST(ProxyChainTest,InvalidHostname)163 TEST(ProxyChainTest, InvalidHostname) {
164 const char* const tests[]{
165 "",
166 "[]",
167 "[foo]",
168 "foo:",
169 "foo:80",
170 ":",
171 "http://foo",
172 "3ffe:2a00:100:7031::1]",
173 "[3ffe:2a00:100:7031::1",
174 "foo.80",
175 };
176
177 for (size_t i = 0; i < std::size(tests); ++i) {
178 SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i]);
179 auto proxy = ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTP,
180 tests[i], 80);
181 EXPECT_FALSE(proxy.IsValid());
182 }
183 }
184
TEST(ProxyChainTest,InvalidPort)185 TEST(ProxyChainTest, InvalidPort) {
186 const char* const tests[]{
187 "-1",
188 "65536",
189 "foo",
190 "0x35",
191 };
192
193 for (size_t i = 0; i < std::size(tests); ++i) {
194 SCOPED_TRACE(base::NumberToString(i) + ": " + tests[i]);
195 auto proxy = ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTP,
196 "foopy", tests[i]);
197 EXPECT_FALSE(proxy.IsValid());
198 }
199 }
200
TEST(ProxyChainTest,SingleProxyChain)201 TEST(ProxyChainTest, SingleProxyChain) {
202 auto proxy_server =
203 ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTPS);
204
205 std::vector<ProxyServer> proxy_servers = {proxy_server};
206 auto proxy = ProxyChain(proxy_servers);
207
208 EXPECT_FALSE(proxy.is_direct());
209 EXPECT_TRUE(proxy.is_single_proxy());
210 EXPECT_FALSE(proxy.is_multi_proxy());
211 ASSERT_EQ(proxy.proxy_servers(), proxy_servers);
212 ASSERT_EQ(proxy.length(), 1u);
213 ASSERT_EQ(proxy.GetProxyServer(0), proxy_server);
214 }
215
TEST(ProxyChainTest,MultiProxyChain)216 TEST(ProxyChainTest, MultiProxyChain) {
217 auto proxy_server1 =
218 ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTPS);
219 auto proxy_server2 =
220 ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS);
221 auto proxy_server3 =
222 ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS);
223
224 std::vector<ProxyServer> proxy_servers = {proxy_server1, proxy_server2,
225 proxy_server3};
226 auto proxy = ProxyChain(proxy_servers);
227
228 EXPECT_FALSE(proxy.is_direct());
229 EXPECT_FALSE(proxy.is_single_proxy());
230 EXPECT_TRUE(proxy.is_multi_proxy());
231 ASSERT_EQ(proxy.proxy_servers(), proxy_servers);
232 ASSERT_EQ(proxy.length(), 3u);
233 ASSERT_EQ(proxy.GetProxyServer(0), proxy_server1);
234 ASSERT_EQ(proxy.GetProxyServer(1), proxy_server2);
235 ASSERT_EQ(proxy.GetProxyServer(2), proxy_server3);
236 }
237
TEST(ProxyChainTest,SplitLast)238 TEST(ProxyChainTest, SplitLast) {
239 auto proxy_server1 =
240 ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTPS);
241 auto proxy_server2 =
242 ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS);
243 auto proxy_server3 =
244 ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS);
245
246 auto chain3 = ProxyChain::ForIpProtection(
247 {proxy_server1, proxy_server2, proxy_server3});
248 EXPECT_EQ(chain3.SplitLast(),
249 std::make_pair(
250 ProxyChain::ForIpProtection({proxy_server1, proxy_server2}),
251 proxy_server3));
252
253 auto chain2 = ProxyChain({proxy_server1, proxy_server2});
254 EXPECT_EQ(chain2.SplitLast(),
255 std::make_pair(ProxyChain({proxy_server1}), proxy_server2));
256
257 auto chain1 = ProxyChain({proxy_server1});
258 EXPECT_EQ(chain1.SplitLast(),
259 std::make_pair(ProxyChain::Direct(), proxy_server1));
260 }
261
TEST(ProxyChainTest,Prefix)262 TEST(ProxyChainTest, Prefix) {
263 auto proxy_server1 =
264 ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTPS);
265 auto proxy_server2 =
266 ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS);
267 auto proxy_server3 =
268 ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS);
269 auto chain = ProxyChain::ForIpProtection(
270 {proxy_server1, proxy_server2, proxy_server3}, /*chain_id=*/2);
271 EXPECT_EQ(chain.Prefix(0), ProxyChain::ForIpProtection({}, /*chain_id=*/2));
272 EXPECT_EQ(chain.Prefix(1),
273 ProxyChain::ForIpProtection({proxy_server1}, /*chain_id=*/2));
274 EXPECT_EQ(chain.Prefix(2),
275 ProxyChain::ForIpProtection({proxy_server1, proxy_server2},
276 /*chain_id=*/2));
277 EXPECT_EQ(chain.Prefix(3),
278 ProxyChain::ForIpProtection(
279 {proxy_server1, proxy_server2, proxy_server3}, /*chain_id=*/2));
280 }
281
TEST(ProxyChainTest,First)282 TEST(ProxyChainTest, First) {
283 auto proxy_server1 =
284 ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTPS);
285 auto proxy_server2 =
286 ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS);
287
288 auto chain = ProxyChain({proxy_server1, proxy_server2});
289 EXPECT_EQ(chain.First(), proxy_server1);
290
291 chain = ProxyChain({proxy_server1});
292 EXPECT_EQ(chain.First(), proxy_server1);
293 }
294
TEST(ProxyChainTest,Last)295 TEST(ProxyChainTest, Last) {
296 auto proxy_server1 =
297 ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTPS);
298 auto proxy_server2 =
299 ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS);
300
301 auto chain = ProxyChain({proxy_server1, proxy_server2});
302 EXPECT_EQ(chain.Last(), proxy_server2);
303
304 chain = ProxyChain({proxy_server1});
305 EXPECT_EQ(chain.Last(), proxy_server1);
306 }
307
TEST(ProxyChainTest,IsForIpProtection)308 TEST(ProxyChainTest, IsForIpProtection) {
309 auto regular_proxy_chain1 = ProxyChain::Direct();
310 EXPECT_FALSE(regular_proxy_chain1.is_for_ip_protection());
311
312 auto ip_protection_proxy_chain1 =
313 ProxyChain::ForIpProtection(std::vector<ProxyServer>());
314 EXPECT_TRUE(ip_protection_proxy_chain1.is_for_ip_protection());
315
316 auto regular_proxy_chain2 =
317 ProxyChain({ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
318 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)});
319 EXPECT_FALSE(regular_proxy_chain2.is_for_ip_protection());
320
321 auto ip_protection_proxy_chain2 = ProxyChain::ForIpProtection(
322 {ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
323 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)});
324 EXPECT_TRUE(ip_protection_proxy_chain2.is_for_ip_protection());
325 }
326
TEST(ProxyChainTest,ForIpProtection)327 TEST(ProxyChainTest, ForIpProtection) {
328 auto ip_protection_proxy_chain1 =
329 ProxyChain::ForIpProtection(std::vector<ProxyServer>());
330 EXPECT_TRUE(ip_protection_proxy_chain1.is_direct());
331 EXPECT_TRUE(ip_protection_proxy_chain1.is_for_ip_protection());
332 EXPECT_EQ(ip_protection_proxy_chain1.ip_protection_chain_id(),
333 ProxyChain::kDefaultIpProtectionChainId);
334
335 auto regular_proxy_chain2 =
336 ProxyChain({ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
337 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)});
338 auto ip_protection_proxy_chain2 = ProxyChain::ForIpProtection(
339 {ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
340 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)});
341 EXPECT_TRUE(ip_protection_proxy_chain2.is_for_ip_protection());
342 EXPECT_EQ(ip_protection_proxy_chain2.ip_protection_chain_id(),
343 ProxyChain::kDefaultIpProtectionChainId);
344 EXPECT_EQ(regular_proxy_chain2.proxy_servers(),
345 ip_protection_proxy_chain2.proxy_servers());
346
347 auto self_assignable_proxy_chain =
348 ProxyChain({ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
349 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)});
350 auto copied_proxy_chain = self_assignable_proxy_chain;
351
352 EXPECT_FALSE(self_assignable_proxy_chain.is_for_ip_protection());
353 EXPECT_EQ(self_assignable_proxy_chain.ip_protection_chain_id(),
354 ProxyChain::kNotIpProtectionChainId);
355
356 self_assignable_proxy_chain = ProxyChain::ForIpProtection(
357 std::move(self_assignable_proxy_chain.proxy_servers()));
358 EXPECT_TRUE(self_assignable_proxy_chain.is_for_ip_protection());
359 EXPECT_EQ(self_assignable_proxy_chain.proxy_servers(),
360 copied_proxy_chain.proxy_servers());
361 EXPECT_EQ(self_assignable_proxy_chain.ip_protection_chain_id(),
362 ProxyChain::kDefaultIpProtectionChainId);
363
364 auto chain_with_id = ProxyChain::ForIpProtection(
365 {ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
366 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)},
367 /*chain_id=*/3);
368 EXPECT_FALSE(chain_with_id.is_direct());
369 EXPECT_TRUE(chain_with_id.is_for_ip_protection());
370 EXPECT_EQ(chain_with_id.ip_protection_chain_id(), 3);
371 }
372
TEST(ProxyChainTest,IsGetToProxyAllowed)373 TEST(ProxyChainTest, IsGetToProxyAllowed) {
374 auto https_server1 =
375 ProxyUriToProxyServer("foo:333", ProxyServer::SCHEME_HTTPS);
376 auto https_server2 =
377 ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS);
378 auto http_server = ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTP);
379 auto socks_server =
380 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_SOCKS4);
381
382 EXPECT_FALSE(ProxyChain::Direct().is_get_to_proxy_allowed());
383 EXPECT_TRUE(ProxyChain({https_server1}).is_get_to_proxy_allowed());
384 EXPECT_TRUE(ProxyChain({http_server}).is_get_to_proxy_allowed());
385 EXPECT_FALSE(ProxyChain({socks_server}).is_get_to_proxy_allowed());
386 EXPECT_FALSE(
387 ProxyChain({https_server1, https_server2}).is_get_to_proxy_allowed());
388 }
389
TEST(ProxyChainTest,IsValid)390 TEST(ProxyChainTest, IsValid) {
391 // Single hop proxy of type Direct is valid.
392 EXPECT_TRUE(ProxyChain::Direct().IsValid());
393
394 auto https1 = ProxyUriToProxyServer("foo:444", ProxyServer::SCHEME_HTTPS);
395 auto https2 = ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS);
396 auto quic1 = ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_QUIC);
397 auto quic2 = ProxyUriToProxyServer("foo:777", ProxyServer::SCHEME_QUIC);
398 auto socks = ProxyUriToProxyServer("foo:777", ProxyServer::SCHEME_SOCKS5);
399
400 EXPECT_TRUE(ProxyChain({https1}).IsValid());
401 EXPECT_FALSE(ProxyChain({quic1}).IsValid());
402 EXPECT_TRUE(ProxyChain({https1, https2}).IsValid());
403 EXPECT_FALSE(ProxyChain({quic1, https1}).IsValid());
404 EXPECT_FALSE(ProxyChain({quic1, quic2, https1, https2}).IsValid());
405 EXPECT_FALSE(ProxyChain({https1, quic2}).IsValid());
406 EXPECT_FALSE(ProxyChain({https1, https2, quic1, quic2}).IsValid());
407 EXPECT_FALSE(ProxyChain({socks, https1}).IsValid());
408 EXPECT_FALSE(ProxyChain({socks, https1, https2}).IsValid());
409 EXPECT_FALSE(ProxyChain({https1, socks}).IsValid());
410 EXPECT_FALSE(ProxyChain({https1, https2, socks}).IsValid());
411
412 // IP protection accepts chains with SCHEME_QUIC, but CHECKs on failure
413 // instead of just creating an invalid chain.
414 auto IppChain = [](std::vector<ProxyServer> proxy_servers) {
415 return ProxyChain::ForIpProtection(std::move(proxy_servers));
416 };
417 EXPECT_TRUE(IppChain({https1}).IsValid());
418 EXPECT_TRUE(IppChain({quic1}).IsValid());
419 EXPECT_TRUE(IppChain({https1, https2}).IsValid());
420 EXPECT_TRUE(IppChain({quic1, https1}).IsValid());
421 EXPECT_TRUE(IppChain({quic1, quic2, https1, https2}).IsValid());
422 EXPECT_CHECK_DEATH(IppChain({https1, quic2}).IsValid());
423 EXPECT_CHECK_DEATH(IppChain({https1, https2, quic1, quic2}).IsValid());
424 EXPECT_CHECK_DEATH(IppChain({socks, https1}).IsValid());
425 EXPECT_CHECK_DEATH(IppChain({socks, https1, https2}).IsValid());
426 EXPECT_CHECK_DEATH(IppChain({https1, socks}).IsValid());
427 EXPECT_CHECK_DEATH(IppChain({https1, https2, socks}).IsValid());
428 }
429
TEST(ProxyChainTest,Unequal)430 TEST(ProxyChainTest, Unequal) {
431 // Ordered proxy chains.
432 std::vector<ProxyChain> proxy_chain_list = {
433 ProxyChain::Direct(),
434 ProxyUriToProxyChain("foo:333", ProxyServer::SCHEME_HTTP),
435 ProxyUriToProxyChain("foo:444", ProxyServer::SCHEME_HTTP),
436 ProxyChain({ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
437 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)}),
438 ProxyUriToProxyChain("socks4://foo:33", ProxyServer::SCHEME_SOCKS4),
439 ProxyUriToProxyChain("http://foo:33", ProxyServer::SCHEME_HTTP),
440 ProxyChain({ProxyUriToProxyChain("bar:33", ProxyServer::SCHEME_HTTP)}),
441 ProxyChain::ForIpProtection(
442 {ProxyUriToProxyServer("foo:555", ProxyServer::SCHEME_HTTPS),
443 ProxyUriToProxyServer("foo:666", ProxyServer::SCHEME_HTTPS)})};
444
445 // Unordered proxy chains.
446 std::set<ProxyChain> proxy_chain_set(proxy_chain_list.begin(),
447 proxy_chain_list.end());
448
449 // Initial proxy chain list and set are equal.
450 ASSERT_EQ(proxy_chain_list.size(), proxy_chain_set.size());
451
452 for (const ProxyChain& proxy_chain1 : proxy_chain_list) {
453 auto proxy_chain2 = proxy_chain_set.begin();
454 // Chain set entries less than `proxy_chain1`.
455 while (*proxy_chain2 < proxy_chain1) {
456 EXPECT_TRUE(*proxy_chain2 < proxy_chain1);
457 EXPECT_FALSE(proxy_chain1 < *proxy_chain2);
458 EXPECT_FALSE(*proxy_chain2 == proxy_chain1);
459 EXPECT_FALSE(proxy_chain1 == *proxy_chain2);
460 ++proxy_chain2;
461 }
462
463 // Chain set entry for `proxy_chain1`.
464 EXPECT_FALSE(*proxy_chain2 < proxy_chain1);
465 EXPECT_FALSE(proxy_chain1 < *proxy_chain2);
466 EXPECT_TRUE(*proxy_chain2 == proxy_chain1);
467 EXPECT_TRUE(proxy_chain1 == *proxy_chain2);
468 ++proxy_chain2;
469
470 // Chain set entries greater than `proxy_chain1`.
471 while (proxy_chain2 != proxy_chain_set.end() &&
472 proxy_chain1 < *proxy_chain2) {
473 EXPECT_FALSE(*proxy_chain2 < proxy_chain1);
474 EXPECT_TRUE(proxy_chain1 < *proxy_chain2);
475 EXPECT_FALSE(*proxy_chain2 == proxy_chain1);
476 EXPECT_FALSE(proxy_chain1 == *proxy_chain2);
477 ++proxy_chain2;
478 }
479 ASSERT_EQ(proxy_chain2, proxy_chain_set.end());
480 }
481 }
482
TEST(ProxyChainTest,Equal)483 TEST(ProxyChainTest, Equal) {
484 ProxyServer proxy_server =
485 ProxyUriToProxyServer("foo:11", ProxyServer::SCHEME_HTTP);
486
487 ProxyChain proxy_chain1 = ProxyChain(proxy_server);
488 ProxyChain proxy_chain2 = ProxyChain(std::vector<ProxyServer>{proxy_server});
489 ProxyChain proxy_chain3 =
490 ProxyChain(ProxyServer::SCHEME_HTTP, HostPortPair("foo", 11));
491
492 EXPECT_FALSE(proxy_chain1 < proxy_chain2);
493 EXPECT_FALSE(proxy_chain2 < proxy_chain1);
494 EXPECT_TRUE(proxy_chain2 == proxy_chain1);
495 EXPECT_TRUE(proxy_chain2 == proxy_chain1);
496
497 EXPECT_FALSE(proxy_chain2 < proxy_chain3);
498 EXPECT_FALSE(proxy_chain3 < proxy_chain2);
499 EXPECT_TRUE(proxy_chain3 == proxy_chain2);
500 EXPECT_TRUE(proxy_chain3 == proxy_chain2);
501 }
502
503 } // namespace
504
505 } // namespace net
506