15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/trace_event_analyzer.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/window_snapshot/window_snapshot.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
22558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/common/net/url_fixer_upper.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/test_switches.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/tracing.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/perf/browser_perf_test.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/perf/perf_test.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents_view.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/browser_test_utils.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h"
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/config/gpu_test_config.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/mock_host_resolver.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkColor.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_switches.h"
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum RunTestFlags {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kNone = 0,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kInternal = 1 << 0,         // Test uses internal test data.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kAllowExternalDNS = 1 << 1, // Test needs external DNS lookup.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kIsGpuCanvasTest = 1 << 2   // Test uses GPU accelerated canvas features.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ThroughputTestFlags {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kSW = 0,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kGPU = 1 << 0,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kCompositorThread = 1 << 1
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSpinUpTimeMs = 4 * 1000;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kRunTimeMs = 10 * 1000;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kIgnoreSomeFrames = 3;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThroughputTest : public BrowserPerfTest {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ThroughputTest(int flags) :
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_gpu_(flags & kGPU),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      use_compositor_thread_(flags & kCompositorThread),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      spinup_time_ms_(kSpinUpTimeMs),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run_time_ms_(kRunTimeMs) {}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This indicates running on GPU bots, not necessarily using the GPU.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsGpuAvailable() const {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CommandLine::ForCurrentProcess()->HasSwitch("enable-gpu");
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse flags from JSON to control the test behavior.
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ParseFlagsFromJSON(const base::FilePath& json_dir,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const std::string& json,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          int index) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<base::Value> root;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    root.reset(base::JSONReader::Read(json));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue* root_list = NULL;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!root.get() || !root->GetAsList(&root_list)) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "JSON missing root list element";
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* item = NULL;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!root_list->GetDictionary(index, &item)) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "index " << index << " not found in JSON";
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string str;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->GetStringASCII("url", &str)) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gurl_ = GURL(str);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (item->GetStringASCII("file", &str)) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath empty;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gurl_ = URLFixerUpper::FixupRelativeFile(empty, empty.AppendASCII(str));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "missing url or file";
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!gurl_.is_valid()) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "invalid url: " << gurl_.possibly_invalid_spec();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath::StringType cache_dir;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->GetString("local_path", &cache_dir))
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      local_cache_path_ = json_dir.Append(cache_dir);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->GetInteger("spinup_time", &num))
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      spinup_time_ms_ = num * 1000;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->GetInteger("run_time", &num))
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      run_time_ms_ = num * 1000;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* pixel = NULL;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->GetDictionary("wait_pixel", &pixel)) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int x, y, r, g, b;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ListValue* color;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pixel->GetInteger("x", &x) &&
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pixel->GetInteger("y", &y) &&
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pixel->GetString("op", &str) &&
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pixel->GetList("color", &color) &&
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          color->GetInteger(0, &r) &&
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          color->GetInteger(1, &g) &&
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          color->GetInteger(2, &b)) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wait_for_pixel_.reset(new WaitPixel(x, y, r, g, b, str));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "invalid wait_pixel args";
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse extra-chrome-flags for extra command line flags.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ParseFlagsFromCommandLine() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!CommandLine::ForCurrentProcess()->HasSwitch(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        switches::kExtraChromeFlags))
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine::StringType flags =
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CommandLine::ForCurrentProcess()->GetSwitchValueNative(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            switches::kExtraChromeFlags);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (MatchPattern(flags, FILE_PATH_LITERAL("*.json:*"))) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine::StringType::size_type colon_pos = flags.find_last_of(':');
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CommandLine::StringType::size_type num_pos = colon_pos + 1;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int index;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(base::StringToInt(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          flags.substr(num_pos, flags.size() - num_pos), &index));
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath filepath(flags.substr(0, colon_pos));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string json;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(file_util::ReadFileToString(filepath, &json));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(ParseFlagsFromJSON(filepath.DirName(), json, index));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gurl_ = GURL(flags);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AllowExternalDNS() {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::RuleBasedHostResolverProc* resolver =
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new net::RuleBasedHostResolverProc(host_resolver());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolver->AllowDirectLookup("*");
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_resolver_override_.reset(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new net::ScopedDefaultHostResolverProc(resolver));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetAllowExternalDNS() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_resolver_override_.reset();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserPerfTest::SetUpCommandLine(command_line);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParseFlagsFromCommandLine();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!local_cache_path_.value().empty()) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If --record-mode is already specified, don't set playback-mode.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!command_line->HasSwitch(switches::kRecordMode))
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        command_line->AppendSwitch(switches::kPlaybackMode);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line->AppendSwitchNative(switches::kDiskCacheDir,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       local_cache_path_.value());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(INFO) << local_cache_path_.value();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are measuring throughput, so we don't want any FPS throttling.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitch(switches::kDisableGpuVsync);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Enable or disable GPU acceleration.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_gpu_) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line->AppendSwitch(switches::kForceCompositingMode);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_compositor_thread_) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(use_gpu_);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line->AppendSwitch(switches::kEnableThreadedCompositing);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command_line->AppendSwitch(switches::kDisableThreadedCompositing);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Wait(int ms) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::RunLoop run_loop;
211a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
212a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        FROM_HERE,
213a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        run_loop.QuitClosure(),
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(ms));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RunThisRunLoop(&run_loop);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Take snapshot of the current tab, encode it as PNG, and save to a SkBitmap.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool TabSnapShotToImage(SkBitmap* bitmap) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(bitmap);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<unsigned char> png;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect root_bounds = browser()->window()->GetBounds();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect tab_contents_bounds;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser()->tab_strip_model()->GetActiveWebContents()->GetView()->
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetContainerBounds(&tab_contents_bounds);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect snapshot_bounds(tab_contents_bounds.x() - root_bounds.x(),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              tab_contents_bounds.y() - root_bounds.y(),
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              tab_contents_bounds.width(),
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              tab_contents_bounds.height());
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::NativeWindow native_window = browser()->window()->GetNativeWindow();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!chrome::GrabWindowSnapshotForUser(native_window, &png,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           snapshot_bounds)) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "browser::GrabWindowSnapShot() failed";
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&*png.begin()),
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               png.size(), bitmap)) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Decode PNG to a SkBitmap failed";
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check a pixel color every second until it passes test.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForPixelColor() {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (wait_for_pixel_.get()) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool success = false;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      do {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkBitmap bitmap;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_TRUE(TabSnapShotToImage(&bitmap));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        success = wait_for_pixel_->IsDone(bitmap);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!success)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Wait(1000);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } while (!success);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // flags is one or more of RunTestFlags OR'd together.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTest(const std::string& test_name, int flags) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set path to test html.
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath test_path;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_path));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_path = test_path.Append(FILE_PATH_LITERAL("perf"));
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (flags & kInternal)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      test_path = test_path.Append(FILE_PATH_LITERAL("private"));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_path = test_path.Append(FILE_PATH_LITERAL("rendering"));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_path = test_path.Append(FILE_PATH_LITERAL("throughput"));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_path = test_path.AppendASCII(test_name);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_path = test_path.Append(FILE_PATH_LITERAL("index.html"));
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_TRUE(base::PathExists(test_path))
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Missing test file: " << test_path.value();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gurl_ = net::FilePathToFileURL(test_path);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunTestWithURL(test_name, flags);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // flags is one or more of RunTestFlags OR'd together.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunCanvasBenchTest(const std::string& test_name, int flags) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set path to test html.
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath test_path;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_path));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_path = test_path.Append(FILE_PATH_LITERAL("perf"));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_path = test_path.Append(FILE_PATH_LITERAL("canvas_bench"));
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_path = test_path.AppendASCII(test_name + ".html");
2897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_TRUE(base::PathExists(test_path))
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Missing test file: " << test_path.value();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gurl_ = net::FilePathToFileURL(test_path);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunTestWithURL(test_name, flags);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // flags is one or more of RunTestFlags OR'd together.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTestWithURL(int flags) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunTestWithURL(gurl_.possibly_invalid_spec(), flags);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // flags is one or more of RunTestFlags OR'd together.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTestWithURL(const std::string& test_name, int flags) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    using trace_analyzer::Query;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    using trace_analyzer::TraceAnalyzer;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    using trace_analyzer::TraceEventVector;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_gpu_ && (flags & kIsGpuCanvasTest) &&
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::win::OSInfo::GetInstance()->version() == base::win::VERSION_XP) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // crbug.com/128208
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Test skipped: GPU canvas tests do not run on XP.";
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_gpu_ && !IsGpuAvailable()) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Test skipped: requires gpu. Pass --enable-gpu on the "
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "command line if use of GPU is desired.";
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (flags & kAllowExternalDNS)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AllowExternalDNS();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string json_events;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TraceEventVector events_sw, events_gpu;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<TraceAnalyzer> analyzer;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << gurl_.possibly_invalid_spec();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui_test_utils::NavigateToURLWithDisposition(
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        browser(), gurl_, CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::WaitForLoadStop(
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        browser()->tab_strip_model()->GetActiveWebContents());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Let the test spin up.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << "Spinning up test...";
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(tracing::BeginTracing("test_gpu"));
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Wait(spinup_time_ms_);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(tracing::EndTracing(&json_events));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait for a pixel color to change (if requested).
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitForPixelColor();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if GPU is rendering:
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    analyzer.reset(TraceAnalyzer::Create(json_events));
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ran_on_gpu = (analyzer->FindEvents(
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Query::EventNameIs("SwapBuffers"), &events_gpu) > 0u);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << "Mode: " << (ran_on_gpu ? "GPU" : "Software");
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(use_gpu_, ran_on_gpu);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Let the test run for a while.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << "Running test...";
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(tracing::BeginTracing("test_fps"));
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Wait(run_time_ms_);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(tracing::EndTracing(&json_events));
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Search for frame ticks. We look for both SW and GPU frame ticks so that
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the test can verify that only one or the other are found.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    analyzer.reset(TraceAnalyzer::Create(json_events));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Query query_sw = Query::EventNameIs("TestFrameTickSW");
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Query query_gpu = Query::EventNameIs("TestFrameTickGPU");
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    analyzer->FindEvents(query_sw, &events_sw);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    analyzer->FindEvents(query_gpu, &events_gpu);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TraceEventVector* frames = NULL;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_gpu_) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frames = &events_gpu;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0u, events_sw.size());
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frames = &events_sw;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0u, events_gpu.size());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_GT(frames->size(), 20u);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cull a few leading and trailing events as they might be unreliable.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TraceEventVector rate_events(frames->begin() + kIgnoreSomeFrames,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 frames->end() - kIgnoreSomeFrames);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    trace_analyzer::RateStats stats;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(GetRateStats(rate_events, &stats, NULL));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << "FPS = " << 1000000.0 / stats.mean_us;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Print perf results.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double mean_ms = stats.mean_us / 1000.0;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double std_dev_ms = stats.standard_deviation_us / 1000.0 / 1000.0;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string trace_name = use_compositor_thread_? "gpu_thread" :
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ran_on_gpu ? "gpu" : "software";
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string mean_and_error = base::StringPrintf("%f,%f", mean_ms,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    std_dev_ms);
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    perf_test::PrintResultMeanAndError(test_name,
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       std::string(),
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       trace_name,
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       mean_and_error,
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       "frame_time",
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       true);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (flags & kAllowExternalDNS)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResetAllowExternalDNS();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Close the tab so that we can quit without timing out during the
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // wait-for-idle stage in browser_test framework.
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    browser()->tab_strip_model()->GetActiveWebContents()->Close();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WaitPixel checks a color against the color at the given pixel coordinates
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of an SkBitmap.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class WaitPixel {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   enum Operator {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     EQUAL,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     NOT_EQUAL
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   };
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WaitPixel(int x, int y, int r, int g, int b, const std::string& op) :
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x_(x), y_(y), r_(r), g_(g), b_(b) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (op == "!=")
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        op_ = EQUAL;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (op == "==")
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        op_ = NOT_EQUAL;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHECK(false) << "op value \"" << op << "\" is not supported";
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool IsDone(const SkBitmap& bitmap) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SkColor color = bitmap.getColor(x_, y_);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int r = SkColorGetR(color);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int g = SkColorGetG(color);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int b = SkColorGetB(color);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(INFO) << "color("  << x_ << "," << y_ << "): " <<
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   r << "," << g << "," << b;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (op_) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case EQUAL:
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return r != r_ || g != g_ || b != b_;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case NOT_EQUAL:
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return r == r_ && g == g_ && b == b_;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int x_;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int y_;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int r_;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int g_;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int b_;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Operator op_;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool use_gpu_;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool use_compositor_thread_;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int spinup_time_ms_;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int run_time_ms_;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath local_cache_path_;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL gurl_;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<net::ScopedDefaultHostResolverProc> host_resolver_override_;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WaitPixel> wait_for_pixel_;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For running tests on GPU:
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThroughputTestGPU : public ThroughputTest {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThroughputTestGPU() : ThroughputTest(kGPU) {}
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For running tests on GPU with the compositor thread:
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThroughputTestThread : public ThroughputTest {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThroughputTestThread() : ThroughputTest(kGPU | kCompositorThread) {}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For running tests on Software:
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThroughputTestSW : public ThroughputTest {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThroughputTestSW() : ThroughputTest(kSW) {}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Tests
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Run this test with a URL on the command line:
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// performance_browser_tests --gtest_also_run_disabled_tests --enable-gpu
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     --gtest_filter=ThroughputTest*URL --extra-chrome-flags=http://...
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or, specify a json file with a list of tests, and the index of the test:
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     --extra-chrome-flags=path/to/tests.json:0
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The json format is an array of tests, for example:
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// {"url":"http://...",
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  "spinup_time":5,
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  "run_time":10,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  "local_path":"path/to/disk-cache-dir",
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  "wait_pixel":{"x":10,"y":10,"op":"!=","color":[24,24,24]}},
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// {"url":"http://..."}
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ]
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The only required argument is url. If local_path is set, the test goes into
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// playback-mode and only loads files from the specified cache. If wait_pixel is
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// specified, then after spinup_time the test waits for the color at the
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// specified pixel coordinate to match the given color with the given operator.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestSW, DISABLED_TestURL) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTestWithURL(kAllowExternalDNS);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, DISABLED_TestURL) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTestWithURL(kAllowExternalDNS);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, Particles) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("particles", kInternal);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestThread, Particles) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("particles", kInternal);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestSW, CanvasDemoSW) {
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas-demo", kInternal);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, CanvasDemoGPU) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas-demo", kInternal | kIsGpuCanvasTest);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestThread, CanvasDemoGPU) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas-demo", kInternal | kIsGpuCanvasTest);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CompositingHugeDivSW timed out on Mac Intel Release GPU bot
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See crbug.com/114781
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stopped producing results in SW: crbug.com/127621
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestSW, DISABLED_CompositingHugeDivSW) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("compositing_huge_div", kNone);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Failing with insufficient frames: crbug.com/127595
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, DISABLED_CompositingHugeDivGPU) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("compositing_huge_div", kNone);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestSW, DrawImageShadowSW) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_with_shadow", kNone);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, DrawImageShadowGPU) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_with_shadow", kNone | kIsGpuCanvasTest);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestThread, DrawImageShadowGPU) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_with_shadow", kNone | kIsGpuCanvasTest);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestSW, CanvasToCanvasDrawSW) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsGpuAvailable() &&
54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      gpu::GPUTestBotConfig::CurrentConfigMatches("MAC AMD"))
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_draw_from_canvas", kNone);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, CanvasToCanvasDrawGPU) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsGpuAvailable() &&
55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      gpu::GPUTestBotConfig::CurrentConfigMatches("MAC AMD"))
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_draw_from_canvas", kNone | kIsGpuCanvasTest);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Failing on windows GPU bots: crbug.com/255192
5617dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochIN_PROC_BROWSER_TEST_F(ThroughputTestSW, DISABLED_CanvasTextSW) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsGpuAvailable() &&
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      gpu::GPUTestBotConfig::CurrentConfigMatches("MAC AMD"))
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_text", kNone);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, CanvasTextGPU) {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_text", kNone | kIsGpuCanvasTest);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestSW, CanvasFillPathSW) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_fill_path", kNone);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, CanvasFillPathGPU) {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest("canvas2d_balls_fill_path", kNone | kIsGpuCanvasTest);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestSW, CanvasSingleImageSW) {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunCanvasBenchTest("single_image", kNone);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, CanvasSingleImageGPU) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsGpuAvailable() &&
58690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      gpu::GPUTestBotConfig::CurrentConfigMatches("MAC AMD"))
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunCanvasBenchTest("single_image", kNone | kIsGpuCanvasTest);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestSW, CanvasManyImagesSW) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunCanvasBenchTest("many_images", kNone);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestGPU, CanvasManyImagesGPU) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunCanvasBenchTest("many_images", kNone | kIsGpuCanvasTest);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ThroughputTestThread, CanvasManyImagesGPU) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunCanvasBenchTest("many_images", kNone | kIsGpuCanvasTest);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
604