proxy_resolver_v8_tracing_unittest.cc 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. // Copyright (c) 2013 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 "services/proxy_resolver/proxy_resolver_v8_tracing.h"
  5. #include <string>
  6. #include <utility>
  7. #include <vector>
  8. #include "base/bind.h"
  9. #include "base/files/file_util.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/path_service.h"
  12. #include "base/run_loop.h"
  13. #include "base/strings/string_number_conversions.h"
  14. #include "base/strings/utf_string_conversions.h"
  15. #include "base/synchronization/waitable_event.h"
  16. #include "base/test/task_environment.h"
  17. #include "base/threading/platform_thread.h"
  18. #include "base/threading/thread_checker.h"
  19. #include "base/values.h"
  20. #include "net/base/net_errors.h"
  21. #include "net/base/network_interfaces.h"
  22. #include "net/base/network_isolation_key.h"
  23. #include "net/base/proxy_string_util.h"
  24. #include "net/base/test_completion_callback.h"
  25. #include "net/log/net_log_with_source.h"
  26. #include "net/proxy_resolution/proxy_info.h"
  27. #include "net/proxy_resolution/proxy_resolve_dns_operation.h"
  28. #include "net/test/event_waiter.h"
  29. #include "net/test/gtest_util.h"
  30. #include "services/proxy_resolver/mock_proxy_host_resolver.h"
  31. #include "testing/gmock/include/gmock/gmock.h"
  32. #include "testing/gtest/include/gtest/gtest.h"
  33. #include "url/gurl.h"
  34. #include "url/origin.h"
  35. using net::test::IsError;
  36. using net::test::IsOk;
  37. namespace proxy_resolver {
  38. namespace {
  39. class ProxyResolverV8TracingTest : public testing::Test {
  40. public:
  41. void TearDown() override {
  42. // Drain any pending messages, which may be left over from cancellation.
  43. // This way they get reliably run as part of the current test, rather than
  44. // spilling into the next test's execution.
  45. base::RunLoop().RunUntilIdle();
  46. }
  47. base::test::TaskEnvironment task_environment_;
  48. };
  49. scoped_refptr<net::PacFileData> LoadScriptData(const char* filename) {
  50. base::FilePath path;
  51. base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
  52. path = path.AppendASCII("services");
  53. path = path.AppendASCII("proxy_resolver");
  54. path = path.AppendASCII("test");
  55. path = path.AppendASCII("data");
  56. path = path.AppendASCII("proxy_resolver_v8_tracing_unittest");
  57. path = path.AppendASCII(filename);
  58. // Try to read the file from disk.
  59. std::string file_contents;
  60. bool ok = base::ReadFileToString(path, &file_contents);
  61. // If we can't load the file from disk, something is misconfigured.
  62. EXPECT_TRUE(ok) << "Failed to read file: " << path.value();
  63. // Load the PAC script into the net::ProxyResolver.
  64. return net::PacFileData::FromUTF8(file_contents);
  65. }
  66. class MockBindings {
  67. public:
  68. explicit MockBindings(ProxyHostResolver* host_resolver)
  69. : host_resolver_(host_resolver) {}
  70. void Alert(const std::u16string& message) {
  71. alerts_.push_back(base::UTF16ToASCII(message));
  72. }
  73. void OnError(int line_number, const std::u16string& error) {
  74. waiter_.NotifyEvent(EVENT_ERROR);
  75. errors_.push_back(std::make_pair(line_number, base::UTF16ToASCII(error)));
  76. if (!error_callback_.is_null())
  77. std::move(error_callback_).Run();
  78. }
  79. ProxyHostResolver* host_resolver() { return host_resolver_; }
  80. std::vector<std::string> GetAlerts() { return alerts_; }
  81. std::vector<std::pair<int, std::string>> GetErrors() { return errors_; }
  82. void RunOnError(base::OnceClosure callback) {
  83. error_callback_ = std::move(callback);
  84. waiter_.WaitForEvent(EVENT_ERROR);
  85. }
  86. std::unique_ptr<ProxyResolverV8Tracing::Bindings> CreateBindings() {
  87. return std::make_unique<ForwardingBindings>(this);
  88. }
  89. private:
  90. class ForwardingBindings : public ProxyResolverV8Tracing::Bindings {
  91. public:
  92. explicit ForwardingBindings(MockBindings* bindings) : bindings_(bindings) {}
  93. // ProxyResolverV8Tracing::Bindings overrides.
  94. void Alert(const std::u16string& message) override {
  95. DCHECK(thread_checker_.CalledOnValidThread());
  96. bindings_->Alert(message);
  97. }
  98. void OnError(int line_number, const std::u16string& error) override {
  99. DCHECK(thread_checker_.CalledOnValidThread());
  100. bindings_->OnError(line_number, error);
  101. }
  102. net::NetLogWithSource GetNetLogWithSource() override {
  103. DCHECK(thread_checker_.CalledOnValidThread());
  104. return net::NetLogWithSource();
  105. }
  106. ProxyHostResolver* GetHostResolver() override {
  107. DCHECK(thread_checker_.CalledOnValidThread());
  108. return bindings_->host_resolver();
  109. }
  110. private:
  111. raw_ptr<MockBindings> bindings_;
  112. base::ThreadChecker thread_checker_;
  113. };
  114. enum Event {
  115. EVENT_ERROR,
  116. };
  117. std::vector<std::string> alerts_;
  118. std::vector<std::pair<int, std::string>> errors_;
  119. const raw_ptr<ProxyHostResolver> host_resolver_;
  120. base::OnceClosure error_callback_;
  121. net::EventWaiter<Event> waiter_;
  122. };
  123. std::unique_ptr<ProxyResolverV8Tracing> CreateResolver(
  124. std::unique_ptr<ProxyResolverV8Tracing::Bindings> bindings,
  125. const char* filename) {
  126. std::unique_ptr<ProxyResolverV8Tracing> resolver;
  127. std::unique_ptr<ProxyResolverV8TracingFactory> factory(
  128. ProxyResolverV8TracingFactory::Create());
  129. net::TestCompletionCallback callback;
  130. std::unique_ptr<net::ProxyResolverFactory::Request> request;
  131. factory->CreateProxyResolverV8Tracing(LoadScriptData(filename),
  132. std::move(bindings), &resolver,
  133. callback.callback(), &request);
  134. EXPECT_THAT(callback.WaitForResult(), IsOk());
  135. EXPECT_TRUE(resolver);
  136. return resolver;
  137. }
  138. TEST_F(ProxyResolverV8TracingTest, Simple) {
  139. MockProxyHostResolver host_resolver;
  140. MockBindings mock_bindings(&host_resolver);
  141. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  142. CreateResolver(mock_bindings.CreateBindings(), "simple.js");
  143. net::TestCompletionCallback callback;
  144. net::ProxyInfo proxy_info;
  145. std::unique_ptr<net::ProxyResolver::Request> req;
  146. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  147. &proxy_info, callback.callback(), &req,
  148. mock_bindings.CreateBindings());
  149. EXPECT_THAT(callback.WaitForResult(), IsOk());
  150. EXPECT_EQ("foo:99", ProxyServerToProxyUri(proxy_info.proxy_server()));
  151. EXPECT_EQ(0u, host_resolver.num_resolve());
  152. // There were no alerts or errors.
  153. EXPECT_TRUE(mock_bindings.GetAlerts().empty());
  154. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  155. }
  156. TEST_F(ProxyResolverV8TracingTest, JavascriptError) {
  157. MockProxyHostResolver host_resolver;
  158. MockBindings mock_bindings(&host_resolver);
  159. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  160. CreateResolver(mock_bindings.CreateBindings(), "error.js");
  161. net::TestCompletionCallback callback;
  162. net::ProxyInfo proxy_info;
  163. std::unique_ptr<net::ProxyResolver::Request> req;
  164. resolver->GetProxyForURL(
  165. GURL("http://throw-an-error/"), net::NetworkIsolationKey(), &proxy_info,
  166. callback.callback(), &req, mock_bindings.CreateBindings());
  167. EXPECT_THAT(callback.WaitForResult(), IsError(net::ERR_PAC_SCRIPT_FAILED));
  168. EXPECT_EQ(0u, host_resolver.num_resolve());
  169. // Check the output -- there was 1 alert and 1 javascript error.
  170. ASSERT_EQ(1u, mock_bindings.GetAlerts().size());
  171. EXPECT_EQ("Prepare to DIE!", mock_bindings.GetAlerts()[0]);
  172. ASSERT_EQ(1u, mock_bindings.GetErrors().size());
  173. EXPECT_EQ(5, mock_bindings.GetErrors()[0].first);
  174. EXPECT_EQ(
  175. "Uncaught TypeError: Cannot read properties of null (reading 'split')",
  176. mock_bindings.GetErrors()[0].second);
  177. }
  178. TEST_F(ProxyResolverV8TracingTest, TooManyAlerts) {
  179. MockProxyHostResolver host_resolver;
  180. MockBindings mock_bindings(&host_resolver);
  181. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  182. CreateResolver(mock_bindings.CreateBindings(), "too_many_alerts.js");
  183. net::TestCompletionCallback callback;
  184. net::ProxyInfo proxy_info;
  185. std::unique_ptr<net::ProxyResolver::Request> req;
  186. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  187. &proxy_info, callback.callback(), &req,
  188. mock_bindings.CreateBindings());
  189. EXPECT_THAT(callback.WaitForResult(), IsOk());
  190. // Iteration1 does a DNS resolve
  191. // Iteration2 exceeds the alert buffer
  192. // Iteration3 runs in blocking mode and completes
  193. EXPECT_EQ("foo:3", ProxyServerToProxyUri(proxy_info.proxy_server()));
  194. EXPECT_EQ(1u, host_resolver.num_resolve());
  195. // No errors.
  196. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  197. // Check the alerts -- the script generated 50 alerts.
  198. std::vector<std::string> alerts = mock_bindings.GetAlerts();
  199. ASSERT_EQ(50u, alerts.size());
  200. for (size_t i = 0; i < alerts.size(); i++) {
  201. EXPECT_EQ("Gee, all these alerts are silly!", alerts[i]);
  202. }
  203. }
  204. // Verify that buffered alerts cannot grow unboundedly, even when the message is
  205. // empty string.
  206. TEST_F(ProxyResolverV8TracingTest, TooManyEmptyAlerts) {
  207. MockProxyHostResolver host_resolver;
  208. MockBindings mock_bindings(&host_resolver);
  209. std::unique_ptr<ProxyResolverV8Tracing> resolver = CreateResolver(
  210. mock_bindings.CreateBindings(), "too_many_empty_alerts.js");
  211. net::TestCompletionCallback callback;
  212. net::ProxyInfo proxy_info;
  213. std::unique_ptr<net::ProxyResolver::Request> req;
  214. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  215. &proxy_info, callback.callback(), &req,
  216. mock_bindings.CreateBindings());
  217. EXPECT_THAT(callback.WaitForResult(), IsOk());
  218. EXPECT_EQ("foo:3", ProxyServerToProxyUri(proxy_info.proxy_server()));
  219. EXPECT_EQ(1u, host_resolver.num_resolve());
  220. // No errors.
  221. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  222. // Check the alerts -- the script generated 1000 alerts.
  223. std::vector<std::string> alerts = mock_bindings.GetAlerts();
  224. ASSERT_EQ(1000u, alerts.size());
  225. for (size_t i = 0; i < alerts.size(); i++) {
  226. EXPECT_EQ("", alerts[i]);
  227. }
  228. }
  229. // This test runs a PAC script that issues a sequence of DNS resolves. The test
  230. // verifies the final result, and that the underlying DNS resolver received
  231. // the correct set of queries.
  232. TEST_F(ProxyResolverV8TracingTest, Dns) {
  233. MockProxyHostResolver host_resolver;
  234. MockBindings mock_bindings(&host_resolver);
  235. host_resolver.SetResult(
  236. net::GetHostName(), net::ProxyResolveDnsOperation::MY_IP_ADDRESS,
  237. net::NetworkIsolationKey(), {net::IPAddress(122, 133, 144, 155)});
  238. host_resolver.SetResult(
  239. net::GetHostName(), net::ProxyResolveDnsOperation::MY_IP_ADDRESS_EX,
  240. net::NetworkIsolationKey(), {net::IPAddress(133, 122, 100, 200)});
  241. host_resolver.SetError("", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  242. net::NetworkIsolationKey());
  243. host_resolver.SetResult("host1", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  244. net::NetworkIsolationKey(),
  245. {net::IPAddress(166, 155, 144, 44)});
  246. net::IPAddress v6_local;
  247. ASSERT_TRUE(v6_local.AssignFromIPLiteral("::1"));
  248. host_resolver.SetResult(
  249. "host1", net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
  250. net::NetworkIsolationKey(), {v6_local, net::IPAddress(192, 168, 1, 1)});
  251. host_resolver.SetError("host2", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  252. net::NetworkIsolationKey());
  253. host_resolver.SetResult("host3", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  254. net::NetworkIsolationKey(),
  255. {net::IPAddress(166, 155, 144, 33)});
  256. host_resolver.SetError("host6", net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
  257. net::NetworkIsolationKey());
  258. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  259. CreateResolver(mock_bindings.CreateBindings(), "dns.js");
  260. net::TestCompletionCallback callback;
  261. net::ProxyInfo proxy_info;
  262. std::unique_ptr<net::ProxyResolver::Request> req;
  263. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  264. &proxy_info, callback.callback(), &req,
  265. mock_bindings.CreateBindings());
  266. EXPECT_THAT(callback.WaitForResult(), IsOk());
  267. // The test does 13 DNS resolution, however only 7 of them are unique.
  268. EXPECT_EQ(7u, host_resolver.num_resolve());
  269. const char* kExpectedResult =
  270. "122.133.144.155-" // myIpAddress()
  271. "null-" // dnsResolve('')
  272. "__1_192.168.1.1-" // dnsResolveEx('host1')
  273. "null-" // dnsResolve('host2')
  274. "166.155.144.33-" // dnsResolve('host3')
  275. "122.133.144.155-" // myIpAddress()
  276. "166.155.144.33-" // dnsResolve('host3')
  277. "__1_192.168.1.1-" // dnsResolveEx('host1')
  278. "122.133.144.155-" // myIpAddress()
  279. "null-" // dnsResolve('host2')
  280. "-" // dnsResolveEx('host6')
  281. "133.122.100.200-" // myIpAddressEx()
  282. "166.155.144.44" // dnsResolve('host1')
  283. ".test:99";
  284. EXPECT_EQ(kExpectedResult, ProxyServerToProxyUri(proxy_info.proxy_server()));
  285. // No errors.
  286. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  287. // The script generated 1 alert.
  288. ASSERT_EQ(1u, mock_bindings.GetAlerts().size());
  289. EXPECT_EQ("iteration: 7", mock_bindings.GetAlerts()[0]);
  290. }
  291. // This test runs a weird PAC script that was designed to defeat the DNS tracing
  292. // optimization. The proxy resolver should detect the inconsistency and
  293. // fall-back to synchronous mode execution.
  294. TEST_F(ProxyResolverV8TracingTest, FallBackToSynchronous1) {
  295. MockProxyHostResolver host_resolver;
  296. MockBindings mock_bindings(&host_resolver);
  297. host_resolver.SetResult("host1", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  298. net::NetworkIsolationKey(),
  299. {net::IPAddress(166, 155, 144, 11)});
  300. host_resolver.SetResult("crazy4", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  301. net::NetworkIsolationKey(),
  302. {net::IPAddress(133, 199, 111, 4)});
  303. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  304. CreateResolver(mock_bindings.CreateBindings(), "global_sideffects1.js");
  305. net::TestCompletionCallback callback;
  306. net::ProxyInfo proxy_info;
  307. std::unique_ptr<net::ProxyResolver::Request> req;
  308. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  309. &proxy_info, callback.callback(), &req,
  310. mock_bindings.CreateBindings());
  311. EXPECT_THAT(callback.WaitForResult(), IsOk());
  312. // The script itself only does 2 DNS resolves per execution, however it
  313. // constructs the hostname using a global counter which changes on each
  314. // invocation.
  315. EXPECT_EQ(3u, host_resolver.num_resolve());
  316. EXPECT_EQ("166.155.144.11-133.199.111.4.test:100",
  317. ProxyServerToProxyUri(proxy_info.proxy_server()));
  318. // No errors.
  319. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  320. ASSERT_EQ(1u, mock_bindings.GetAlerts().size());
  321. EXPECT_EQ("iteration: 4", mock_bindings.GetAlerts()[0]);
  322. }
  323. // This test runs a weird PAC script that was designed to defeat the DNS tracing
  324. // optimization. The proxy resolver should detect the inconsistency and
  325. // fall-back to synchronous mode execution.
  326. TEST_F(ProxyResolverV8TracingTest, FallBackToSynchronous2) {
  327. MockProxyHostResolver host_resolver;
  328. MockBindings mock_bindings(&host_resolver);
  329. host_resolver.SetResult("host1", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  330. net::NetworkIsolationKey(),
  331. {net::IPAddress(166, 155, 144, 11)});
  332. host_resolver.SetResult("host2", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  333. net::NetworkIsolationKey(),
  334. {net::IPAddress(166, 155, 144, 22)});
  335. host_resolver.SetResult("host3", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  336. net::NetworkIsolationKey(),
  337. {net::IPAddress(166, 155, 144, 33)});
  338. host_resolver.SetResult("host4", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  339. net::NetworkIsolationKey(),
  340. {net::IPAddress(166, 155, 144, 44)});
  341. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  342. CreateResolver(mock_bindings.CreateBindings(), "global_sideffects2.js");
  343. net::TestCompletionCallback callback;
  344. net::ProxyInfo proxy_info;
  345. std::unique_ptr<net::ProxyResolver::Request> req;
  346. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  347. &proxy_info, callback.callback(), &req,
  348. mock_bindings.CreateBindings());
  349. EXPECT_THAT(callback.WaitForResult(), IsOk());
  350. EXPECT_EQ(3u, host_resolver.num_resolve());
  351. EXPECT_EQ("166.155.144.44.test:100",
  352. ProxyServerToProxyUri(proxy_info.proxy_server()));
  353. // There were no alerts or errors.
  354. EXPECT_TRUE(mock_bindings.GetAlerts().empty());
  355. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  356. }
  357. // This test runs a weird PAC script that yields a never ending sequence
  358. // of DNS resolves when restarting. Running it will hit the maximum
  359. // DNS resolves per request limit (20) after which every DNS resolve will
  360. // fail.
  361. TEST_F(ProxyResolverV8TracingTest, InfiniteDNSSequence) {
  362. MockProxyHostResolver host_resolver;
  363. MockBindings mock_bindings(&host_resolver);
  364. for (int i = 0; i < 21; ++i) {
  365. host_resolver.SetResult("host" + base::NumberToString(i),
  366. net::ProxyResolveDnsOperation::DNS_RESOLVE,
  367. net::NetworkIsolationKey(),
  368. {net::IPAddress(166, 155, 144, 11)});
  369. }
  370. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  371. CreateResolver(mock_bindings.CreateBindings(), "global_sideffects3.js");
  372. net::TestCompletionCallback callback;
  373. net::ProxyInfo proxy_info;
  374. std::unique_ptr<net::ProxyResolver::Request> req;
  375. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  376. &proxy_info, callback.callback(), &req,
  377. mock_bindings.CreateBindings());
  378. EXPECT_THAT(callback.WaitForResult(), IsOk());
  379. EXPECT_EQ(20u, host_resolver.num_resolve());
  380. EXPECT_EQ(
  381. "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
  382. "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
  383. "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
  384. "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
  385. "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
  386. "null:21",
  387. ProxyServerToProxyUri(proxy_info.proxy_server()));
  388. // No errors.
  389. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  390. // 1 alert.
  391. EXPECT_EQ(1u, mock_bindings.GetAlerts().size());
  392. EXPECT_EQ("iteration: 21", mock_bindings.GetAlerts()[0]);
  393. }
  394. // This test runs a weird PAC script that yields a never ending sequence
  395. // of DNS resolves when restarting. Running it will hit the maximum
  396. // DNS resolves per request limit (20) after which every DNS resolve will
  397. // fail.
  398. TEST_F(ProxyResolverV8TracingTest, InfiniteDNSSequence2) {
  399. MockProxyHostResolver host_resolver;
  400. MockBindings mock_bindings(&host_resolver);
  401. host_resolver.SetResult(
  402. net::GetHostName(), net::ProxyResolveDnsOperation::MY_IP_ADDRESS,
  403. net::NetworkIsolationKey(), {net::IPAddress(122, 133, 144, 155)});
  404. for (int i = 0; i < 21; ++i) {
  405. host_resolver.SetResult("host" + base::NumberToString(i),
  406. net::ProxyResolveDnsOperation::DNS_RESOLVE,
  407. net::NetworkIsolationKey(),
  408. {net::IPAddress(166, 155, 144, 11)});
  409. }
  410. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  411. CreateResolver(mock_bindings.CreateBindings(), "global_sideffects4.js");
  412. net::TestCompletionCallback callback;
  413. net::ProxyInfo proxy_info;
  414. std::unique_ptr<net::ProxyResolver::Request> req;
  415. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  416. &proxy_info, callback.callback(), &req,
  417. mock_bindings.CreateBindings());
  418. EXPECT_THAT(callback.WaitForResult(), IsOk());
  419. EXPECT_EQ(20u, host_resolver.num_resolve());
  420. EXPECT_EQ("null21:34", ProxyServerToProxyUri(proxy_info.proxy_server()));
  421. // No errors.
  422. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  423. // 1 alert.
  424. EXPECT_EQ(1u, mock_bindings.GetAlerts().size());
  425. EXPECT_EQ("iteration: 21", mock_bindings.GetAlerts()[0]);
  426. }
  427. void DnsDuringInitHelper(bool synchronous_host_resolver) {
  428. MockProxyHostResolver host_resolver(synchronous_host_resolver);
  429. MockBindings mock_bindings(&host_resolver);
  430. host_resolver.SetResult("host1", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  431. net::NetworkIsolationKey(),
  432. {net::IPAddress(91, 13, 12, 1)});
  433. host_resolver.SetResult("host2", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  434. net::NetworkIsolationKey(),
  435. {net::IPAddress(91, 13, 12, 2)});
  436. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  437. CreateResolver(mock_bindings.CreateBindings(), "dns_during_init.js");
  438. // Initialization did 2 dnsResolves.
  439. EXPECT_EQ(2u, host_resolver.num_resolve());
  440. host_resolver.SetResult("host1", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  441. net::NetworkIsolationKey(),
  442. {net::IPAddress(145, 88, 13, 3)});
  443. host_resolver.SetResult("host2", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  444. net::NetworkIsolationKey(),
  445. {net::IPAddress(137, 89, 8, 45)});
  446. net::TestCompletionCallback callback;
  447. net::ProxyInfo proxy_info;
  448. std::unique_ptr<net::ProxyResolver::Request> req;
  449. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  450. &proxy_info, callback.callback(), &req,
  451. mock_bindings.CreateBindings());
  452. EXPECT_THAT(callback.WaitForResult(), IsOk());
  453. // Fetched host1 and host2 again, since the ones done during initialization
  454. // should not have been cached.
  455. EXPECT_EQ(4u, host_resolver.num_resolve());
  456. EXPECT_EQ("91.13.12.1-91.13.12.2-145.88.13.3-137.89.8.45.test:99",
  457. ProxyServerToProxyUri(proxy_info.proxy_server()));
  458. // 2 alerts.
  459. ASSERT_EQ(2u, mock_bindings.GetAlerts().size());
  460. EXPECT_EQ("Watsup", mock_bindings.GetAlerts()[0]);
  461. EXPECT_EQ("Watsup2", mock_bindings.GetAlerts()[1]);
  462. }
  463. // Tests a PAC script which does DNS resolves during initialization.
  464. TEST_F(ProxyResolverV8TracingTest, DnsDuringInit) {
  465. // Test with both both a host resolver that always completes asynchronously,
  466. // and then again with one that completes synchronously.
  467. DnsDuringInitHelper(false);
  468. DnsDuringInitHelper(true);
  469. }
  470. void CrashCallback(int) {
  471. // Be extra sure that if the callback ever gets invoked, the test will fail.
  472. CHECK(false);
  473. }
  474. // Start some requests, cancel them all, and then destroy the resolver.
  475. // Note the execution order for this test can vary. Since multiple
  476. // threads are involved, the cancellation may be received a different
  477. // times.
  478. TEST_F(ProxyResolverV8TracingTest, CancelAll) {
  479. MockProxyHostResolver host_resolver;
  480. MockBindings mock_bindings(&host_resolver);
  481. host_resolver.FailAll();
  482. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  483. CreateResolver(mock_bindings.CreateBindings(), "dns.js");
  484. const size_t kNumRequests = 5;
  485. net::ProxyInfo proxy_info[kNumRequests];
  486. std::unique_ptr<net::ProxyResolver::Request> request[kNumRequests];
  487. for (size_t i = 0; i < kNumRequests; ++i) {
  488. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  489. &proxy_info[i], base::BindOnce(&CrashCallback),
  490. &request[i], mock_bindings.CreateBindings());
  491. }
  492. for (size_t i = 0; i < kNumRequests; ++i) {
  493. request[i].reset();
  494. }
  495. }
  496. // Note the execution order for this test can vary. Since multiple
  497. // threads are involved, the cancellation may be received a different
  498. // times.
  499. TEST_F(ProxyResolverV8TracingTest, CancelSome) {
  500. MockProxyHostResolver host_resolver;
  501. MockBindings mock_bindings(&host_resolver);
  502. host_resolver.FailAll();
  503. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  504. CreateResolver(mock_bindings.CreateBindings(), "dns.js");
  505. net::ProxyInfo proxy_info1;
  506. net::ProxyInfo proxy_info2;
  507. std::unique_ptr<net::ProxyResolver::Request> request1;
  508. std::unique_ptr<net::ProxyResolver::Request> request2;
  509. net::TestCompletionCallback callback;
  510. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  511. &proxy_info1, base::BindOnce(&CrashCallback),
  512. &request1, mock_bindings.CreateBindings());
  513. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  514. &proxy_info2, callback.callback(), &request2,
  515. mock_bindings.CreateBindings());
  516. request1.reset();
  517. EXPECT_THAT(callback.WaitForResult(), IsOk());
  518. }
  519. // Cancel a request after it has finished running on the worker thread, and has
  520. // posted a task the completion task back to origin thread.
  521. TEST_F(ProxyResolverV8TracingTest, CancelWhilePendingCompletionTask) {
  522. MockProxyHostResolver host_resolver;
  523. MockBindings mock_bindings(&host_resolver);
  524. host_resolver.FailAll();
  525. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  526. CreateResolver(mock_bindings.CreateBindings(), "error.js");
  527. net::ProxyInfo proxy_info1;
  528. net::ProxyInfo proxy_info2;
  529. std::unique_ptr<net::ProxyResolver::Request> request1;
  530. std::unique_ptr<net::ProxyResolver::Request> request2;
  531. net::TestCompletionCallback callback;
  532. resolver->GetProxyForURL(GURL("http://throw-an-error/"),
  533. net::NetworkIsolationKey(), &proxy_info1,
  534. base::BindOnce(&CrashCallback), &request1,
  535. mock_bindings.CreateBindings());
  536. // Wait until the first request has finished running on the worker thread.
  537. // Cancel the first request, while it is running its completion task on
  538. // the origin thread. Reset deletes Request opject which cancels the request.
  539. mock_bindings.RunOnError(
  540. base::BindOnce(&std::unique_ptr<net::ProxyResolver::Request>::reset,
  541. base::Unretained(&request1), nullptr));
  542. // Start another request, to make sure it is able to complete.
  543. resolver->GetProxyForURL(GURL("http://i-have-no-idea-what-im-doing/"),
  544. net::NetworkIsolationKey(), &proxy_info2,
  545. callback.callback(), &request2,
  546. mock_bindings.CreateBindings());
  547. EXPECT_THAT(callback.WaitForResult(), IsOk());
  548. EXPECT_EQ("i-approve-this-message:42",
  549. ProxyServerToProxyUri(proxy_info2.proxy_server()));
  550. }
  551. // This cancellation test exercises a more predictable cancellation codepath --
  552. // when the request has an outstanding DNS request in flight.
  553. TEST_F(ProxyResolverV8TracingTest, CancelWhileOutstandingNonBlockingDns) {
  554. base::RunLoop run_loop1;
  555. HangingProxyHostResolver host_resolver(run_loop1.QuitClosure());
  556. MockBindings mock_bindings(&host_resolver);
  557. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  558. CreateResolver(mock_bindings.CreateBindings(), "dns.js");
  559. net::ProxyInfo proxy_info1;
  560. net::ProxyInfo proxy_info2;
  561. std::unique_ptr<net::ProxyResolver::Request> request1;
  562. std::unique_ptr<net::ProxyResolver::Request> request2;
  563. resolver->GetProxyForURL(GURL("http://foo/req1"), net::NetworkIsolationKey(),
  564. &proxy_info1, base::BindOnce(&CrashCallback),
  565. &request1, mock_bindings.CreateBindings());
  566. run_loop1.Run();
  567. base::RunLoop run_loop2;
  568. host_resolver.set_hang_callback(run_loop2.QuitClosure());
  569. resolver->GetProxyForURL(GURL("http://foo/req2"), net::NetworkIsolationKey(),
  570. &proxy_info2, base::BindOnce(&CrashCallback),
  571. &request2, mock_bindings.CreateBindings());
  572. run_loop2.Run();
  573. request1.reset();
  574. request2.reset();
  575. EXPECT_EQ(2, host_resolver.num_cancelled_requests());
  576. // After leaving this scope, the net::ProxyResolver is destroyed.
  577. // This should not cause any problems, as the outstanding work
  578. // should have been cancelled.
  579. }
  580. void CancelRequestAndPause(
  581. std::unique_ptr<net::ProxyResolver::Request>* request,
  582. base::RunLoop* run_loop) {
  583. request->reset();
  584. // Sleep for a little bit. This makes it more likely for the worker
  585. // thread to have returned from its call, and serves as a regression
  586. // test for http://crbug.com/173373.
  587. base::PlatformThread::Sleep(base::Milliseconds(30));
  588. run_loop->Quit();
  589. }
  590. // In non-blocking mode, the worker thread actually does block for
  591. // a short time to see if the result is in the DNS cache. Test
  592. // cancellation while the worker thread is waiting on this event.
  593. TEST_F(ProxyResolverV8TracingTest, CancelWhileBlockedInNonBlockingDns) {
  594. HangingProxyHostResolver host_resolver;
  595. MockBindings mock_bindings(&host_resolver);
  596. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  597. CreateResolver(mock_bindings.CreateBindings(), "dns.js");
  598. net::ProxyInfo proxy_info;
  599. std::unique_ptr<net::ProxyResolver::Request> request;
  600. base::RunLoop run_loop;
  601. host_resolver.set_hang_callback(
  602. base::BindRepeating(&CancelRequestAndPause, &request, &run_loop));
  603. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  604. &proxy_info, base::BindOnce(&CrashCallback),
  605. &request, mock_bindings.CreateBindings());
  606. run_loop.Run();
  607. }
  608. // Cancel the request while there is a pending DNS request, however before
  609. // the request is sent to the host resolver.
  610. TEST_F(ProxyResolverV8TracingTest, CancelWhileBlockedInNonBlockingDns2) {
  611. MockProxyHostResolver host_resolver;
  612. MockBindings mock_bindings(&host_resolver);
  613. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  614. CreateResolver(mock_bindings.CreateBindings(), "dns.js");
  615. net::ProxyInfo proxy_info;
  616. std::unique_ptr<net::ProxyResolver::Request> request;
  617. resolver->GetProxyForURL(GURL("http://foo/"), net::NetworkIsolationKey(),
  618. &proxy_info, base::BindOnce(&CrashCallback),
  619. &request, mock_bindings.CreateBindings());
  620. // Wait a bit, so the DNS task has hopefully been posted. The test will
  621. // work whatever the delay is here, but it is most useful if the delay
  622. // is large enough to allow a task to be posted back.
  623. base::PlatformThread::Sleep(base::Milliseconds(10));
  624. request.reset();
  625. EXPECT_EQ(0u, host_resolver.num_resolve());
  626. }
  627. TEST_F(ProxyResolverV8TracingTest,
  628. CancelCreateResolverWhileOutstandingBlockingDns) {
  629. base::RunLoop run_loop;
  630. HangingProxyHostResolver host_resolver(run_loop.QuitClosure());
  631. MockBindings mock_bindings(&host_resolver);
  632. std::unique_ptr<ProxyResolverV8TracingFactory> factory(
  633. ProxyResolverV8TracingFactory::Create());
  634. std::unique_ptr<ProxyResolverV8Tracing> resolver;
  635. std::unique_ptr<net::ProxyResolverFactory::Request> request;
  636. factory->CreateProxyResolverV8Tracing(
  637. LoadScriptData("dns_during_init.js"), mock_bindings.CreateBindings(),
  638. &resolver, base::BindOnce(&CrashCallback), &request);
  639. run_loop.Run();
  640. request.reset();
  641. EXPECT_EQ(1, host_resolver.num_cancelled_requests());
  642. }
  643. TEST_F(ProxyResolverV8TracingTest, DeleteFactoryWhileOutstandingBlockingDns) {
  644. base::RunLoop run_loop;
  645. HangingProxyHostResolver host_resolver(run_loop.QuitClosure());
  646. MockBindings mock_bindings(&host_resolver);
  647. std::unique_ptr<ProxyResolverV8Tracing> resolver;
  648. std::unique_ptr<net::ProxyResolverFactory::Request> request;
  649. {
  650. std::unique_ptr<ProxyResolverV8TracingFactory> factory(
  651. ProxyResolverV8TracingFactory::Create());
  652. factory->CreateProxyResolverV8Tracing(
  653. LoadScriptData("dns_during_init.js"), mock_bindings.CreateBindings(),
  654. &resolver, base::BindOnce(&CrashCallback), &request);
  655. run_loop.Run();
  656. }
  657. EXPECT_EQ(1, host_resolver.num_cancelled_requests());
  658. }
  659. TEST_F(ProxyResolverV8TracingTest, ErrorLoadingScript) {
  660. HangingProxyHostResolver host_resolver;
  661. MockBindings mock_bindings(&host_resolver);
  662. std::unique_ptr<ProxyResolverV8TracingFactory> factory(
  663. ProxyResolverV8TracingFactory::Create());
  664. std::unique_ptr<ProxyResolverV8Tracing> resolver;
  665. std::unique_ptr<net::ProxyResolverFactory::Request> request;
  666. net::TestCompletionCallback callback;
  667. factory->CreateProxyResolverV8Tracing(
  668. LoadScriptData("error_on_load.js"), mock_bindings.CreateBindings(),
  669. &resolver, callback.callback(), &request);
  670. EXPECT_THAT(callback.WaitForResult(), IsError(net::ERR_PAC_SCRIPT_FAILED));
  671. EXPECT_FALSE(resolver);
  672. }
  673. // This tests that the execution of a PAC script is terminated when the DNS
  674. // dependencies are missing. If the test fails, then it will hang.
  675. TEST_F(ProxyResolverV8TracingTest, Terminate) {
  676. MockProxyHostResolver host_resolver;
  677. MockBindings mock_bindings(&host_resolver);
  678. host_resolver.SetResult("host1", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  679. net::NetworkIsolationKey(),
  680. {net::IPAddress(182, 111, 0, 222)});
  681. host_resolver.SetResult(
  682. "host2", net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
  683. net::NetworkIsolationKey(), {net::IPAddress(111, 33, 44, 55)});
  684. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  685. CreateResolver(mock_bindings.CreateBindings(), "terminate.js");
  686. net::TestCompletionCallback callback;
  687. net::ProxyInfo proxy_info;
  688. std::unique_ptr<net::ProxyResolver::Request> req;
  689. resolver->GetProxyForURL(
  690. GURL("http://foopy/req1"), net::NetworkIsolationKey(), &proxy_info,
  691. callback.callback(), &req, mock_bindings.CreateBindings());
  692. EXPECT_THAT(callback.WaitForResult(), IsOk());
  693. // The test does 2 DNS resolutions.
  694. EXPECT_EQ(2u, host_resolver.num_resolve());
  695. EXPECT_EQ("foopy:3", ProxyServerToProxyUri(proxy_info.proxy_server()));
  696. // No errors or alerts.
  697. EXPECT_TRUE(mock_bindings.GetErrors().empty());
  698. EXPECT_TRUE(mock_bindings.GetAlerts().empty());
  699. }
  700. // Tests that multiple instances of ProxyResolverV8Tracing can coexist and run
  701. // correctly at the same time. This is relevant because at the moment (time
  702. // this test was written) each ProxyResolverV8Tracing creates its own thread to
  703. // run V8 on, however each thread is operating on the same v8::Isolate.
  704. TEST_F(ProxyResolverV8TracingTest, MultipleResolvers) {
  705. // ------------------------
  706. // Setup resolver0
  707. // ------------------------
  708. MockProxyHostResolver host_resolver0;
  709. MockBindings mock_bindings0(&host_resolver0);
  710. host_resolver0.SetResult(
  711. net::GetHostName(), net::ProxyResolveDnsOperation::MY_IP_ADDRESS,
  712. net::NetworkIsolationKey(), {net::IPAddress(122, 133, 144, 155)});
  713. host_resolver0.SetResult(
  714. net::GetHostName(), net::ProxyResolveDnsOperation::MY_IP_ADDRESS_EX,
  715. net::NetworkIsolationKey(), {net::IPAddress(133, 122, 100, 200)});
  716. host_resolver0.SetError("", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  717. net::NetworkIsolationKey());
  718. host_resolver0.SetResult("host1", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  719. net::NetworkIsolationKey(),
  720. {net::IPAddress(166, 155, 144, 44)});
  721. net::IPAddress v6_local;
  722. ASSERT_TRUE(v6_local.AssignFromIPLiteral("::1"));
  723. host_resolver0.SetResult(
  724. "host1", net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
  725. net::NetworkIsolationKey(), {v6_local, net::IPAddress(192, 168, 1, 1)});
  726. host_resolver0.SetError("host2", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  727. net::NetworkIsolationKey());
  728. host_resolver0.SetResult("host3", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  729. net::NetworkIsolationKey(),
  730. {net::IPAddress(166, 155, 144, 33)});
  731. host_resolver0.SetError("host6",
  732. net::ProxyResolveDnsOperation::DNS_RESOLVE_EX,
  733. net::NetworkIsolationKey());
  734. std::unique_ptr<ProxyResolverV8Tracing> resolver0 =
  735. CreateResolver(mock_bindings0.CreateBindings(), "dns.js");
  736. // ------------------------
  737. // Setup resolver1
  738. // ------------------------
  739. std::unique_ptr<ProxyResolverV8Tracing> resolver1 =
  740. CreateResolver(mock_bindings0.CreateBindings(), "dns.js");
  741. // ------------------------
  742. // Setup resolver2
  743. // ------------------------
  744. std::unique_ptr<ProxyResolverV8Tracing> resolver2 =
  745. CreateResolver(mock_bindings0.CreateBindings(), "simple.js");
  746. // ------------------------
  747. // Setup resolver3
  748. // ------------------------
  749. MockProxyHostResolver host_resolver3;
  750. MockBindings mock_bindings3(&host_resolver3);
  751. host_resolver3.SetResult("foo", net::ProxyResolveDnsOperation::DNS_RESOLVE,
  752. net::NetworkIsolationKey(),
  753. {net::IPAddress(166, 155, 144, 33)});
  754. std::unique_ptr<ProxyResolverV8Tracing> resolver3 =
  755. CreateResolver(mock_bindings3.CreateBindings(), "simple_dns.js");
  756. // ------------------------
  757. // Queue up work for each resolver (which will be running in parallel).
  758. // ------------------------
  759. ProxyResolverV8Tracing* resolver[] = {
  760. resolver0.get(),
  761. resolver1.get(),
  762. resolver2.get(),
  763. resolver3.get(),
  764. };
  765. const size_t kNumResolvers = std::size(resolver);
  766. const size_t kNumIterations = 20;
  767. const size_t kNumResults = kNumResolvers * kNumIterations;
  768. net::TestCompletionCallback callback[kNumResults];
  769. net::ProxyInfo proxy_info[kNumResults];
  770. std::unique_ptr<net::ProxyResolver::Request> request[kNumResults];
  771. for (size_t i = 0; i < kNumResults; ++i) {
  772. size_t resolver_i = i % kNumResolvers;
  773. resolver[resolver_i]->GetProxyForURL(
  774. GURL("http://foo/"), net::NetworkIsolationKey(), &proxy_info[i],
  775. callback[i].callback(), &request[i],
  776. resolver_i == 3 ? mock_bindings3.CreateBindings()
  777. : mock_bindings0.CreateBindings());
  778. }
  779. // ------------------------
  780. // Verify all of the results.
  781. // ------------------------
  782. const char* kExpectedForDnsJs =
  783. "122.133.144.155-" // myIpAddress()
  784. "null-" // dnsResolve('')
  785. "__1_192.168.1.1-" // dnsResolveEx('host1')
  786. "null-" // dnsResolve('host2')
  787. "166.155.144.33-" // dnsResolve('host3')
  788. "122.133.144.155-" // myIpAddress()
  789. "166.155.144.33-" // dnsResolve('host3')
  790. "__1_192.168.1.1-" // dnsResolveEx('host1')
  791. "122.133.144.155-" // myIpAddress()
  792. "null-" // dnsResolve('host2')
  793. "-" // dnsResolveEx('host6')
  794. "133.122.100.200-" // myIpAddressEx()
  795. "166.155.144.44" // dnsResolve('host1')
  796. ".test:99";
  797. for (size_t i = 0; i < kNumResults; ++i) {
  798. size_t resolver_i = i % kNumResolvers;
  799. EXPECT_THAT(callback[i].WaitForResult(), IsOk());
  800. std::string proxy_uri = ProxyServerToProxyUri(proxy_info[i].proxy_server());
  801. if (resolver_i == 0 || resolver_i == 1) {
  802. EXPECT_EQ(kExpectedForDnsJs, proxy_uri);
  803. } else if (resolver_i == 2) {
  804. EXPECT_EQ("foo:99", proxy_uri);
  805. } else if (resolver_i == 3) {
  806. EXPECT_EQ("166.155.144.33.test:",
  807. proxy_uri.substr(0, proxy_uri.find(':') + 1));
  808. } else {
  809. NOTREACHED();
  810. }
  811. }
  812. }
  813. // Make sure that NetworkIsolationKeys passed to the ProxyResolverV8Tracing are
  814. // passed to the ProxyHostResolver. Does this by making a MockProxyHostResolver
  815. // return different results for the same host based on what
  816. // net::NetworkIsolationKey is used, and then using a PAC script that returns
  817. // the IP address a hostname resolves to as a proxy using the two different
  818. // NetworkIsolationKeys, checking the results.
  819. TEST_F(ProxyResolverV8TracingTest, NetworkIsolationKey) {
  820. const url::Origin kOrigin1 = url::Origin::Create(GURL("https://foo.test/"));
  821. const net::NetworkIsolationKey kNetworkIsolationKey1(kOrigin1, kOrigin1);
  822. const net::IPAddress kIPAddress1(1, 2, 3, 4);
  823. const url::Origin kOrigin2 = url::Origin::Create(GURL("https://bar.test/"));
  824. const net::NetworkIsolationKey kNetworkIsolationKey2(kOrigin2, kOrigin2);
  825. const net::IPAddress kIPAddress2(5, 6, 7, 8);
  826. const char kHost[] = "host.test";
  827. MockProxyHostResolver host_resolver;
  828. MockBindings mock_bindings(&host_resolver);
  829. host_resolver.SetResult(kHost, net::ProxyResolveDnsOperation::DNS_RESOLVE,
  830. kNetworkIsolationKey1, {kIPAddress1});
  831. host_resolver.SetResult(kHost, net::ProxyResolveDnsOperation::DNS_RESOLVE,
  832. kNetworkIsolationKey2, {kIPAddress2});
  833. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  834. CreateResolver(mock_bindings.CreateBindings(), "simple_dns.js");
  835. net::TestCompletionCallback callback;
  836. std::unique_ptr<net::ProxyResolver::Request> req;
  837. net::ProxyInfo proxy_info1;
  838. resolver->GetProxyForURL(GURL("https://host.test/"), kNetworkIsolationKey1,
  839. &proxy_info1, callback.callback(), &req,
  840. mock_bindings.CreateBindings());
  841. EXPECT_THAT(callback.WaitForResult(), IsOk());
  842. EXPECT_EQ(2u, host_resolver.num_resolve());
  843. EXPECT_EQ(kIPAddress1.ToString() + ".test",
  844. proxy_info1.proxy_server().host_port_pair().host());
  845. net::ProxyInfo proxy_info2;
  846. resolver->GetProxyForURL(GURL("https://host.test/"), kNetworkIsolationKey2,
  847. &proxy_info2, callback.callback(), &req,
  848. mock_bindings.CreateBindings());
  849. EXPECT_THAT(callback.WaitForResult(), IsOk());
  850. EXPECT_EQ(4u, host_resolver.num_resolve());
  851. EXPECT_EQ(kIPAddress2.ToString() + ".test",
  852. proxy_info2.proxy_server().host_port_pair().host());
  853. }
  854. // Make sure that net::NetworkIsolationKey is not passed to the
  855. // ProxyHostResolver when looking up either myIpAddress() or myIpAddressEx().
  856. // This allows their values to be cached across NetworkIsolationKeys. This test
  857. // works by having the ProxyHostResolver return different results based on the
  858. // net::NetworkIsolationKey used, and then running a PAC script that returns a
  859. // result containing the IP address contained by both values, checking the
  860. // resulting value.
  861. TEST_F(ProxyResolverV8TracingTest, MyIPAddressWithNetworkIsolationKey) {
  862. const url::Origin kOrigin = url::Origin::Create(GURL("https://foo.test/"));
  863. const net::NetworkIsolationKey kNetworkIsolationKey(kOrigin, kOrigin);
  864. MockProxyHostResolver host_resolver;
  865. MockBindings mock_bindings(&host_resolver);
  866. host_resolver.SetResult(
  867. net::GetHostName(), net::ProxyResolveDnsOperation::MY_IP_ADDRESS,
  868. net::NetworkIsolationKey(), {net::IPAddress(1, 2, 3, 4)});
  869. host_resolver.SetResult(
  870. net::GetHostName(), net::ProxyResolveDnsOperation::MY_IP_ADDRESS_EX,
  871. net::NetworkIsolationKey(), {net::IPAddress(5, 6, 7, 8)});
  872. host_resolver.SetResult(net::GetHostName(),
  873. net::ProxyResolveDnsOperation::MY_IP_ADDRESS,
  874. kNetworkIsolationKey, {net::IPAddress(9, 9, 9, 9)});
  875. host_resolver.SetResult(
  876. net::GetHostName(), net::ProxyResolveDnsOperation::MY_IP_ADDRESS_EX,
  877. kNetworkIsolationKey, {net::IPAddress(10, 10, 10, 10)});
  878. std::unique_ptr<ProxyResolverV8Tracing> resolver =
  879. CreateResolver(mock_bindings.CreateBindings(), "my_ip_address.js");
  880. net::TestCompletionCallback callback;
  881. std::unique_ptr<net::ProxyResolver::Request> req;
  882. net::ProxyInfo proxy_info;
  883. resolver->GetProxyForURL(GURL("https://host.test/"), kNetworkIsolationKey,
  884. &proxy_info, callback.callback(), &req,
  885. mock_bindings.CreateBindings());
  886. EXPECT_THAT(callback.WaitForResult(), IsOk());
  887. EXPECT_EQ(2u, host_resolver.num_resolve());
  888. EXPECT_EQ("1.2.3.4-5.6.7.8.test",
  889. proxy_info.proxy_server().host_port_pair().host());
  890. }
  891. } // namespace
  892. } // namespace proxy_resolver