1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com// Use of this source code is governed by a BSD-style license that can be
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com// found in the LICENSE file.
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com#include "base/base_paths.h"
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com#include "base/file_util.h"
7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com#include "base/path_service.h"
8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com#include "base/perftimer.h"
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "base/string_util.h"
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "net/base/mock_host_resolver.h"
113ef45971cdc72a20db91e8bce37e16d669947e4arobertphillips@google.com#include "net/base/net_errors.h"
129ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "net/proxy/proxy_info.h"
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "net/proxy/proxy_resolver_js_bindings.h"
148c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com#include "net/proxy/proxy_resolver_v8.h"
15494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com#include "net/test/test_server.h"
161c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#include "testing/gtest/include/gtest/gtest.h"
171c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com
181c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#if defined(OS_WIN)
191c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#include "net/proxy/proxy_resolver_winhttp.h"
201c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#elif defined(OS_MACOSX)
211c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#include "net/proxy/proxy_resolver_mac.h"
221c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com#endif
231c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com
24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// This class holds the URL to use for resolving, and the expected result.
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// We track the expected result in order to make sure the performance
26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// test is actually resolving URLs properly, otherwise the perf numbers
279df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com// are meaningless :-)
28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstruct PacQuery {
29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com  const char* query_url;
309011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com  const char* expected_result;
31ff0114918f0420778dfac164d810af08eadbac26reed@google.com};
329011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com
33b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com// Entry listing which PAC scripts to load, and which URLs to try resolving.
341c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com// |queries| should be terminated by {NULL, NULL}. A sentinel is used
3552373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.com// rather than a length, to simplify using initializer lists.
361c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.comstruct PacPerfTest {
371c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com  const char* pac_name;
381c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com  PacQuery queries[100];
3952373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.com
4052373f2a535a319f6b6d4a144e57491c5e56e311skia.committer@gmail.com  // Returns the actual number of entries in |queries| (assumes NULL sentinel).
411c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com  int NumQueries() const;
421c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com};
431c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com
441c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com// List of performance tests.
459011c23655acf4186fca1789daee7e94fc0bbe61reed@google.comstatic PacPerfTest kPerfTests[] = {
46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com  // This test uses an ad-blocker PAC script. This script is very heavily
47494c51acb7f414d5ff5e7ab617a7bc32becb6381robertphillips@google.com  // regular expression oriented, and has no dependencies on the current
484d1d95c61576960796347e1dd5006d878e9d2dc0djsollen@google.com  // IP address, or DNS resolving of hosts.
49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com  { "no-ads.pac",
501e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    { // queries:
51bb6529fbc4553260f434113a62a20af53c525649reed@google.com      {"http://www.google.com", "DIRECT"},
52bb6529fbc4553260f434113a62a20af53c525649reed@google.com      {"http://www.imdb.com/photos/cmsicons/x", "PROXY 0.0.0.0:3421"},
539011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com      {"http://www.imdb.com/x", "DIRECT"},
54b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com      {"http://www.staples.com/", "DIRECT"},
55b75bc072b3a26cafed919573412f7ca2fd8d0953skia.committer@gmail.com      {"http://www.staples.com/pixeltracker/x", "PROXY 0.0.0.0:3421"},
568c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com      {"http://www.staples.com/pixel/x", "DIRECT"},
57a29024e9f900c5565340a27e925bca7d0f6ea8e1skia.committer@gmail.com      {"http://www.foobar.com", "DIRECT"},
58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com      {"http://www.foobarbaz.com/x/y/z", "DIRECT"},
591c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com      {"http://www.testurl1.com/index.html", "DIRECT"},
601c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com      {"http://www.testurl2.com", "DIRECT"},
611c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com      {"https://www.sample/pirate/arrrrrr", "DIRECT"},
629df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com      {NULL, NULL}
639df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com    },
649df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com  },
65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com};
66740de996d9e77a695864fdd8b89b4bd55f8d304asenorblanco@chromium.org
67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint PacPerfTest::NumQueries() const {
68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com  for (size_t i = 0; i < arraysize(queries); ++i) {
69cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.com    if (queries[i].query_url == NULL)
709df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com      return i;
719df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com  }
721c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com  NOTREACHED();  // Bad definition.
731c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com  return 0;
749df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com}
759df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com
761c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com// The number of URLs to resolve when testing a PAC script.
77935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.comconst int kNumIterations = 500;
78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// Helper class to run through all the performance tests using the specified
80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// proxy resolver implementation.
819df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.comclass PacPerfSuiteRunner {
821c6d325f96b5b14e7b0c76680d6a15d6517d2eb6robertphillips@google.com public:
83ff0114918f0420778dfac164d810af08eadbac26reed@google.com  // |resolver_name| is the label used when logging the results.
84ff0114918f0420778dfac164d810af08eadbac26reed@google.com  PacPerfSuiteRunner(net::ProxyResolver* resolver,
85ff0114918f0420778dfac164d810af08eadbac26reed@google.com                     const std::string& resolver_name)
864c003748338174e594471cfe86ec1bcb53fda6fcreed@google.com      : resolver_(resolver),
87935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com        resolver_name_(resolver_name),
88ff0114918f0420778dfac164d810af08eadbac26reed@google.com        test_server_(net::TestServer::TYPE_HTTP,
89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            FilePath(FILE_PATH_LITERAL("net/data/proxy_resolver_perftest"))) {
90ff0114918f0420778dfac164d810af08eadbac26reed@google.com  }
91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
929df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com  void RunAllTests() {
939df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com    ASSERT_TRUE(test_server_.Start());
949df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com    for (size_t i = 0; i < arraysize(kPerfTests); ++i) {
959df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com      const PacPerfTest& test_data = kPerfTests[i];
969df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com      RunTest(test_data.pac_name,
979df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com              test_data.queries,
989df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com              test_data.NumQueries());
999df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com    }
1009df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com  }
1019df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com
1029df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com private:
1039df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com  void RunTest(const std::string& script_name,
1049df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com               const PacQuery* queries,
1059df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com               int queries_len) {
1069df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com    if (!resolver_->expects_pac_bytes()) {
107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com      GURL pac_url =
108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com          test_server_.GetURL(std::string("files/") + script_name);
109ff0114918f0420778dfac164d810af08eadbac26reed@google.com      int rv = resolver_->SetPacScript(
110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com          net::ProxyResolverScriptData::FromURL(pac_url), NULL);
1119df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com      EXPECT_EQ(net::OK, rv);
112ff0114918f0420778dfac164d810af08eadbac26reed@google.com    } else {
113740de996d9e77a695864fdd8b89b4bd55f8d304asenorblanco@chromium.org      LoadPacScriptIntoResolver(script_name);
1149df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com    }
115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // Do a query to warm things up. In the case of internal-fetch proxy
117ff0114918f0420778dfac164d810af08eadbac26reed@google.com    // resolvers, the first resolve will be slow since it has to download
118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // the PAC script.
119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com      net::ProxyInfo proxy_info;
121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com      int result = resolver_->GetProxyForURL(
122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com          GURL("http://www.warmup.com"), &proxy_info, NULL, NULL,
123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com          net::BoundNetLog());
124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com      ASSERT_EQ(net::OK, result);
1259df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com    }
126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
127740de996d9e77a695864fdd8b89b4bd55f8d304asenorblanco@chromium.org    // Start the perf timer.
128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    std::string perf_test_name = resolver_name_ + "_" + script_name;
129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    PerfTimeLogger timer(perf_test_name.c_str());
1309011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com
131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int i = 0; i < kNumIterations; ++i) {
132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com      // Round-robin between URLs to resolve.
133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com      const PacQuery& query = queries[i % queries_len];
134ff0114918f0420778dfac164d810af08eadbac26reed@google.com
1359011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com      // Resolve.
1369011c23655acf4186fca1789daee7e94fc0bbe61reed@google.com      net::ProxyInfo proxy_info;
1379df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com      int result = resolver_->GetProxyForURL(GURL(query.query_url),
138740de996d9e77a695864fdd8b89b4bd55f8d304asenorblanco@chromium.org                                             &proxy_info, NULL, NULL,
139ff0114918f0420778dfac164d810af08eadbac26reed@google.com                                             net::BoundNetLog());
140935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
141ff0114918f0420778dfac164d810af08eadbac26reed@google.com      // Check that the result was correct. Note that ToPacString() and
142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com      // ASSERT_EQ() are fast, so they won't skew the results.
1439df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com      ASSERT_EQ(net::OK, result);
1449df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com      ASSERT_EQ(query.expected_result, proxy_info.ToPacString());
145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1478c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com    // Print how long the test ran for.
1488c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com    timer.Done();
1498c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com  }
1509df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com
1518c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com  // Read the PAC script from disk and initialize the proxy resolver with it.
1529df4d78e401f921b65012987f8d2049e9da5cef5robertphillips@google.com  void LoadPacScriptIntoResolver(const std::string& script_name) {
1538c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com    FilePath path;
1548c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com    PathService::Get(base::DIR_SOURCE_ROOT, &path);
1558c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com    path = path.AppendASCII("net");
1561e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    path = path.AppendASCII("data");
1571e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    path = path.AppendASCII("proxy_resolver_perftest");
158bb6529fbc4553260f434113a62a20af53c525649reed@google.com    path = path.AppendASCII(script_name);
159bb6529fbc4553260f434113a62a20af53c525649reed@google.com
1601e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    // Try to read the file from disk.
1611e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    std::string file_contents;
1621e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    bool ok = file_util::ReadFileToString(path, &file_contents);
1631e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com
1641e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    // If we can't load the file from disk, something is misconfigured.
1651e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    LOG_IF(ERROR, !ok) << "Failed to read file: " << path.value();
1661e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    ASSERT_TRUE(ok);
1671e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com
1681e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    // Load the PAC script into the ProxyResolver.
1691e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    int rv = resolver_->SetPacScript(
1701e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com        net::ProxyResolverScriptData::FromUTF8(file_contents), NULL);
1711e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com    EXPECT_EQ(net::OK, rv);
1721e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com  }
1731e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com
1741e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com  net::ProxyResolver* resolver_;
1751e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com  std::string resolver_name_;
176bb6529fbc4553260f434113a62a20af53c525649reed@google.com  net::TestServer test_server_;
177bb6529fbc4553260f434113a62a20af53c525649reed@google.com};
1781e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com
1791e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com#if defined(OS_WIN)
1801e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.comTEST(ProxyResolverPerfTest, ProxyResolverWinHttp) {
1811e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com  net::ProxyResolverWinHttp resolver;
182bb6529fbc4553260f434113a62a20af53c525649reed@google.com  PacPerfSuiteRunner runner(&resolver, "ProxyResolverWinHttp");
183bb6529fbc4553260f434113a62a20af53c525649reed@google.com  runner.RunAllTests();
184bb6529fbc4553260f434113a62a20af53c525649reed@google.com}
185bb6529fbc4553260f434113a62a20af53c525649reed@google.com#elif defined(OS_MACOSX)
186bb6529fbc4553260f434113a62a20af53c525649reed@google.comTEST(ProxyResolverPerfTest, ProxyResolverMac) {
187bb6529fbc4553260f434113a62a20af53c525649reed@google.com  net::ProxyResolverMac resolver;
188bb6529fbc4553260f434113a62a20af53c525649reed@google.com  PacPerfSuiteRunner runner(&resolver, "ProxyResolverMac");
189bb6529fbc4553260f434113a62a20af53c525649reed@google.com  runner.RunAllTests();
190bb6529fbc4553260f434113a62a20af53c525649reed@google.com}
191bb6529fbc4553260f434113a62a20af53c525649reed@google.com#endif
1921e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com
1931e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.comTEST(ProxyResolverPerfTest, ProxyResolverV8) {
1941e7ce9786525318f59d4c5a6efa6819c6ff9ab84reed@google.com  net::ProxyResolverJSBindings* js_bindings =
19536f4104a411facb6f8a7b4830e9235c2a1610265reed@google.com      net::ProxyResolverJSBindings::CreateDefault(
19636f4104a411facb6f8a7b4830e9235c2a1610265reed@google.com          new net::MockHostResolver, NULL);
19736f4104a411facb6f8a7b4830e9235c2a1610265reed@google.com
1980cd465fde832c0441cad1809ee7b18e50266e385reed@google.com  net::ProxyResolverV8 resolver(js_bindings);
1990cd465fde832c0441cad1809ee7b18e50266e385reed@google.com  PacPerfSuiteRunner runner(&resolver, "ProxyResolverV8");
2008c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com  runner.RunAllTests();
2010cbcedc421fcbf653d1ceace58b14c07fed197a4humper@google.com}
2028c2ce5e8666e05e662d8bfcb8aaf89cdb34c3a0ehumper@google.com
2030cbcedc421fcbf653d1ceace58b14c07fed197a4humper@google.com