#include "net/proxy_resolution/proxy_list.h"
#include <vector>
#include "net/base/net_errors.h"
#include "net/base/proxy_server.h"
#include "net/base/proxy_string_util.h"
#include "net/log/net_log_with_source.h"
#include "net/proxy_resolution/proxy_retry_info.h"
#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using net::test::IsOk;
namespace net {
namespace {
TEST(ProxyListTest, SetFromPacString) {
const struct {
const char* pac_input;
const char* pac_output;
} tests[] = {
{ "PROXY foopy:10",
"PROXY foopy:10",
},
{ " DIRECT",
"DIRECT",
},
{ "PROXY foopy1 ; proxy foopy2;\t DIRECT",
"PROXY foopy1:80;PROXY foopy2:80;DIRECT",
},
{ "proxy foopy1 ; SOCKS foopy2",
"PROXY foopy1:80;SOCKS foopy2:1080",
},
{ "DIRECT ; proxy foopy1 ; DIRECT ; SOCKS5 foopy2;DIRECT ",
"DIRECT;PROXY foopy1:80;DIRECT;SOCKS5 foopy2:1080;DIRECT",
},
{ "DIRECT ; proxy foopy1:80; DIRECT ; DIRECT",
"DIRECT;PROXY foopy1:80;DIRECT;DIRECT",
},
{ "PROXY-foopy:10",
"DIRECT",
},
{ "PROXY",
"DIRECT",
},
{ "PROXY foopy1 ; JUNK ; JUNK ; SOCKS5 foopy2 ; ;",
"PROXY foopy1:80;SOCKS5 foopy2:1080",
},
};
for (const auto& test : tests) {
ProxyList list;
list.SetFromPacString(test.pac_input);
EXPECT_EQ(test.pac_output, list.ToPacString());
EXPECT_FALSE(list.IsEmpty());
}
}
TEST(ProxyListTest, RemoveProxiesWithoutScheme) {
const struct {
const char* pac_input;
int filter;
const char* filtered_pac_output;
} tests[] = {
{ "PROXY foopy:10 ; SOCKS5 foopy2 ; SOCKS foopy11 ; PROXY foopy3 ; DIRECT",
ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_HTTP,
"PROXY foopy:10;PROXY foopy3:80;DIRECT",
},
{ "PROXY foopy:10 ; SOCKS5 foopy2",
ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_SOCKS4,
"",
},
};
for (const auto& test : tests) {
ProxyList list;
list.SetFromPacString(test.pac_input);
list.RemoveProxiesWithoutScheme(test.filter);
EXPECT_EQ(test.filtered_pac_output, list.ToPacString());
}
}
TEST(ProxyListTest, DeprioritizeBadProxies) {
ProxyRetryInfo proxy_retry_info;
proxy_retry_info.bad_until = base::TimeTicks::Now() + base::Days(1);
{
ProxyList list;
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
ProxyRetryInfoMap retry_info_map;
list.DeprioritizeBadProxies(retry_info_map);
EXPECT_EQ("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80",
list.ToPacString());
}
{
ProxyList list;
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
ProxyRetryInfoMap retry_info_map;
retry_info_map["foopy1:80"] = proxy_retry_info;
retry_info_map["foopy3:80"] = proxy_retry_info;
retry_info_map["socks5://localhost:1080"] = proxy_retry_info;
list.DeprioritizeBadProxies(retry_info_map);
EXPECT_EQ("PROXY foopy2:80;PROXY foopy1:80;PROXY foopy3:80",
list.ToPacString());
}
{
ProxyList list;
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
ProxyRetryInfoMap retry_info_map;
retry_info_map["foopy1:80"] = proxy_retry_info;
retry_info_map["foopy2:80"] = proxy_retry_info;
retry_info_map["foopy3:80"] = proxy_retry_info;
list.DeprioritizeBadProxies(retry_info_map);
EXPECT_EQ("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80",
list.ToPacString());
}
{
ProxyList list;
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
ProxyRetryInfoMap retry_info_map;
retry_info_map["foopy1:80"] = proxy_retry_info;
proxy_retry_info.try_while_bad = false;
retry_info_map["foopy3:80"] = proxy_retry_info;
proxy_retry_info.try_while_bad = true;
retry_info_map["socks5://localhost:1080"] = proxy_retry_info;
list.DeprioritizeBadProxies(retry_info_map);
EXPECT_EQ("PROXY foopy2:80;PROXY foopy1:80",
list.ToPacString());
}
}
TEST(ProxyListTest, UpdateRetryInfoOnFallback) {
{
ProxyList list;
ProxyRetryInfoMap retry_info_map;
NetLogWithSource net_log;
ProxyServer proxy_server(
ProxyUriToProxyServer("foopy1:80", ProxyServer::SCHEME_HTTP));
std::vector<ProxyServer> bad_proxies;
bad_proxies.push_back(proxy_server);
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true,
bad_proxies, ERR_PROXY_CONNECTION_FAILED,
net_log);
EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy1:80"));
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
retry_info_map[ProxyServerToProxyUri(proxy_server)].net_error);
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy3:80"));
}
{
ProxyList list;
ProxyRetryInfoMap retry_info_map;
NetLogWithSource net_log;
ProxyServer proxy_server(
ProxyUriToProxyServer("foopy1:80", ProxyServer::SCHEME_HTTP));
std::vector<ProxyServer> bad_proxies;
bad_proxies.push_back(proxy_server);
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true,
bad_proxies, OK, net_log);
EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy1:80"));
EXPECT_THAT(retry_info_map[ProxyServerToProxyUri(proxy_server)].net_error,
IsOk());
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy3:80"));
}
{
ProxyList list;
ProxyRetryInfoMap retry_info_map;
NetLogWithSource net_log;
ProxyServer proxy_server =
ProxyUriToProxyServer("foopy3:80", ProxyServer::SCHEME_HTTP);
std::vector<ProxyServer> bad_proxies;
bad_proxies.push_back(proxy_server);
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true,
bad_proxies, ERR_NAME_RESOLUTION_FAILED,
net_log);
EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy1:80"));
EXPECT_EQ(ERR_NAME_RESOLUTION_FAILED,
retry_info_map[ProxyServerToProxyUri(proxy_server)].net_error);
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy3:80"));
}
{
ProxyList list;
ProxyRetryInfoMap retry_info_map;
NetLogWithSource net_log;
ProxyServer proxy_server =
ProxyUriToProxyServer("foopy2:80", ProxyServer::SCHEME_HTTP);
std::vector<ProxyServer> bad_proxies;
bad_proxies.push_back(proxy_server);
list.SetFromPacString("DIRECT;PROXY foopy2:80;PROXY foopy3:80");
list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true,
bad_proxies, OK, net_log);
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy3:80"));
}
{
ProxyList list;
ProxyRetryInfoMap retry_info_map;
NetLogWithSource net_log;
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true,
std::vector<ProxyServer>(),
ERR_PROXY_CONNECTION_FAILED, net_log);
list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(1), false,
std::vector<ProxyServer>(), OK, net_log);
EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy1:80"));
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
retry_info_map["foopy1:80"].net_error);
EXPECT_TRUE(retry_info_map["foopy1:80"].try_while_bad);
EXPECT_EQ(base::Seconds(60), retry_info_map["foopy1:80"].current_delay);
EXPECT_GT(retry_info_map["foopy1:80"].bad_until,
base::TimeTicks::Now() + base::Seconds(30));
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy3:80"));
}
{
ProxyList list;
ProxyRetryInfoMap retry_info_map;
NetLogWithSource net_log;
list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80");
list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(1), false,
std::vector<ProxyServer>(), OK, net_log);
list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true,
std::vector<ProxyServer>(),
ERR_PROXY_CONNECTION_FAILED, net_log);
EXPECT_TRUE(retry_info_map.end() != retry_info_map.find("foopy1:80"));
EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
retry_info_map["foopy1:80"].net_error);
EXPECT_TRUE(retry_info_map["foopy1:80"].try_while_bad);
EXPECT_EQ(base::Seconds(60), retry_info_map["foopy1:80"].current_delay);
EXPECT_GT(retry_info_map["foopy1:80"].bad_until,
base::TimeTicks::Now() + base::Seconds(30));
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy2:80"));
EXPECT_TRUE(retry_info_map.end() == retry_info_map.find("foopy3:80"));
}
}
}
}