12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h"
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_view_host.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_paths.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_switches.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/test/browser_test_utils.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/shell/shell.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/test/content_browser_test.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/test/content_browser_test_utils.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "gpu/config/gpu_test_config.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_util.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkColor.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gl/gl_switches.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/snapshot/snapshot.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)enum ReferenceImageOption {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kReferenceImageLocal,
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kReferenceImageCheckedIn,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kReferenceImageNone  // Only check a few key pixels.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct ReferencePixel {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int x, y;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned char r, g, b;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Command line flag for overriding the default location for putting generated
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// test images that do not match references.
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kGeneratedDir[] = "generated-dir";
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Command line flag for overriding the default location for reference images.
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kReferenceDir[] = "reference-dir";
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Command line flag for Chromium build revision.
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kBuildRevision[] = "build-revision";
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Reads and decodes a PNG image to a bitmap. Returns true on success. The PNG
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// should have been encoded using |gfx::PNGCodec::Encode|.
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ReadPNGFile(const base::FilePath& file_path, SkBitmap* bitmap) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(bitmap);
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath abs_path(base::MakeAbsoluteFilePath(file_path));
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (abs_path.empty())
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string png_data;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return file_util::ReadFileToString(abs_path, &png_data) &&
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&png_data[0]),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               png_data.length(),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               bitmap);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Encodes a bitmap into a PNG and write to disk. Returns true on success. The
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// parent directory does not have to exist.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WritePNGFile(const SkBitmap& bitmap, const base::FilePath& file_path) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<unsigned char> png_data;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &png_data) &&
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      file_util::CreateDirectory(file_path.DirName())) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int bytes_written = file_util::WriteFile(
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        file_path, reinterpret_cast<char*>(&png_data[0]), png_data.size());
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (bytes_written == static_cast<int>(png_data.size()))
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Write an empty file, whose name indicates the chrome revision when the ref
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// image was generated.
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WriteREVFile(const base::FilePath& file_path) {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_util::CreateDirectory(file_path.DirName())) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char one_byte = 0;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int bytes_written = file_util::WriteFile(file_path, &one_byte, 1);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (bytes_written == 1)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace anonymous
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test fixture for GPU image comparison tests.
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(kkania): Document how to add to/modify these tests.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GpuPixelBrowserTest : public ContentBrowserTest {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuPixelBrowserTest()
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : ref_img_revision_(0),
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ref_img_revision_no_older_than_(0),
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ref_img_option_(kReferenceImageNone) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
108a031efa9dbd9b321781674193e8ac7636d47eb1dBen Murdoch  virtual void SetUp() {
109a031efa9dbd9b321781674193e8ac7636d47eb1dBen Murdoch    // We expect real pixel output for these tests.
110a031efa9dbd9b321781674193e8ac7636d47eb1dBen Murdoch    UseRealGLContexts();
111a031efa9dbd9b321781674193e8ac7636d47eb1dBen Murdoch
112a031efa9dbd9b321781674193e8ac7636d47eb1dBen Murdoch    ContentBrowserTest::SetUp();
113a031efa9dbd9b321781674193e8ac7636d47eb1dBen Murdoch  }
114a031efa9dbd9b321781674193e8ac7636d47eb1dBen Murdoch
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    command_line->AppendSwitchASCII(switches::kTestGLLib,
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    "libllvmpipe.so");
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ContentBrowserTest::SetUpInProcessBrowserTestFixture();
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CommandLine* command_line = CommandLine::ForCurrentProcess();
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (command_line->HasSwitch(switches::kUseGpuInTests))
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ref_img_option_ = kReferenceImageLocal;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (command_line->HasSwitch(kBuildRevision))
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      build_revision_ = command_line->GetSwitchValueASCII(kBuildRevision);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_data_dir_));
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_data_dir_ = test_data_dir_.AppendASCII("gpu");
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (command_line->HasSwitch(kGeneratedDir))
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      generated_img_dir_ = command_line->GetSwitchValuePath(kGeneratedDir);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      generated_img_dir_ = test_data_dir_.AppendASCII("generated");
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (ref_img_option_) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case kReferenceImageLocal:
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (command_line->HasSwitch(kReferenceDir))
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ref_img_dir_ = command_line->GetSwitchValuePath(kReferenceDir);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        else
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ref_img_dir_ = test_data_dir_.AppendASCII("gpu_reference");
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case kReferenceImageCheckedIn:
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ref_img_dir_ = test_data_dir_.AppendASCII("llvmpipe_reference");
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default:
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    test_name_ = testing::UnitTest::GetInstance()->current_test_info()->name();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* test_status_prefixes[] = {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "DISABLED_", "FLAKY_", "FAILS_", "MANUAL_"};
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < arraysize(test_status_prefixes); ++i) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ReplaceFirstSubstringAfterOffset(
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &test_name_, 0, test_status_prefixes[i], std::string());
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the existing ref image was saved from an revision older than the
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ref_img_update_revision, refresh the ref image.
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RunPixelTest(const gfx::Size& tab_container_size,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const base::FilePath& url,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    int64 ref_img_update_revision,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const ReferencePixel* ref_pixels,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    size_t ref_pixel_count) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ref_img_option_ == kReferenceImageLocal) {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ref_img_revision_no_older_than_ = ref_img_update_revision;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ObtainLocalRefImageRevision();
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DOMMessageQueue message_queue;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NavigateToURL(shell(), net::FilePathToFileURL(url));
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string message;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Wait for notification that page is loaded.
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(message_queue.WaitForMessage(&message));
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_STREQ("\"SUCCESS\"", message.c_str()) << message;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkBitmap bitmap;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(TabSnapShotToImage(&bitmap, tab_container_size));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool same_pixels = true;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ref_img_option_ == kReferenceImageNone && ref_pixels && ref_pixel_count)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      same_pixels = ComparePixels(bitmap, ref_pixels, ref_pixel_count);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      same_pixels = CompareImages(bitmap);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(same_pixels);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath& test_data_dir() const {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return test_data_dir_;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath test_data_dir_;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath generated_img_dir_;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath ref_img_dir_;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 ref_img_revision_;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string build_revision_;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The name of the test, with any special prefixes dropped.
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string test_name_;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Any local ref image generated from older revision is ignored.
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 ref_img_revision_no_older_than_;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Whether use locally generated ref images, or checked in ref images, or
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // simply check a few key pixels.
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReferenceImageOption ref_img_option_;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compares the generated bitmap with the appropriate reference image on disk.
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true iff the images were the same.
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If no valid reference image exists, save the generated bitmap to the disk.
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The image format is:
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     <test_name>_<revision>.png
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // E.g.,
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     WebGLTeapot_19762.png
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The number is the chromium revision that generated the image.
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // On failure or on ref image generation, the image and diff image will be
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // written to disk. The formats are:
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     FAIL_<ref_image_name>, DIFF_<ref_image_name>
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // E.g.,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     FAIL_WebGLTeapot_19762.png, DIFF_WebGLTeapot_19762.png
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool CompareImages(const SkBitmap& gen_bmp) {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkBitmap ref_bmp_on_disk;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath img_path = ref_img_dir_.AppendASCII(test_name_ + ".png");
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool found_ref_img = ReadPNGFile(img_path, &ref_bmp_on_disk);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!found_ref_img && ref_img_option_ == kReferenceImageCheckedIn) {
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Couldn't find reference image: "
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << img_path.value();
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // No image to compare to, exit early.
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const SkBitmap* ref_bmp;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool save_gen = false;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool save_diff = true;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool rt = true;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((ref_img_revision_ <= 0 && ref_img_option_ == kReferenceImageLocal) ||
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !found_ref_img) {
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath rev_path = ref_img_dir_.AppendASCII(
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          test_name_ + "_" + build_revision_ + ".rev");
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!WritePNGFile(gen_bmp, img_path)) {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(ERROR) << "Can't save generated image to: "
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << img_path.value()
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " as future reference.";
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rt = false;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(INFO) << "Saved reference image to: "
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  << img_path.value();
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rt) {
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (!WriteREVFile(rev_path)) {
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          LOG(ERROR) << "Can't save revision file to: "
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     << rev_path.value();
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          rt = false;
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          base::DeleteFile(img_path, false);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          LOG(INFO) << "Saved revision file to: "
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    << rev_path.value();
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (ref_img_revision_ > 0) {
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(ERROR) << "Can't read the local ref image: "
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << img_path.value()
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << ", reset it.";
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rt = false;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If we re-generate the ref image, we save the gen and diff images so
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // the ref image can be uploaded to the server and be viewed later.
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      save_gen = true;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      save_diff = true;
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ref_bmp = &gen_bmp;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ref_bmp = &ref_bmp_on_disk;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkBitmap diff_bmp;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ref_bmp->width() != gen_bmp.width() ||
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ref_bmp->height() != gen_bmp.height()) {
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << "Dimensions do not match (Expected) vs (Actual):"
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << "(" << ref_bmp->width() << "x" << ref_bmp->height()
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              << ") vs. "
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << "(" << gen_bmp.width() << "x" << gen_bmp.height() << ")";
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (ref_img_option_ == kReferenceImageLocal)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        save_gen = true;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rt = false;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Compare pixels and create a simple diff image.
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int diff_pixels_count = 0;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      diff_bmp.setConfig(SkBitmap::kARGB_8888_Config,
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         gen_bmp.width(), gen_bmp.height());
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      diff_bmp.allocPixels();
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      diff_bmp.eraseColor(SK_ColorWHITE);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SkAutoLockPixels lock_bmp(gen_bmp);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SkAutoLockPixels lock_ref_bmp(*ref_bmp);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SkAutoLockPixels lock_diff_bmp(diff_bmp);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // The reference images were saved with no alpha channel. Use the mask to
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // set alpha to 0.
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uint32_t kAlphaMask = 0x00FFFFFF;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (int x = 0; x < gen_bmp.width(); ++x) {
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (int y = 0; y < gen_bmp.height(); ++y) {
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if ((*gen_bmp.getAddr32(x, y) & kAlphaMask) !=
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (*ref_bmp->getAddr32(x, y) & kAlphaMask)) {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ++diff_pixels_count;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            *diff_bmp.getAddr32(x, y) = 192 << 16;  // red
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (diff_pixels_count > 0) {
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(ERROR) << diff_pixels_count
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << " pixels do not match.";
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (ref_img_option_ == kReferenceImageLocal) {
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          save_gen = true;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          save_diff = true;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rt = false;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string ref_img_filename = img_path.BaseName().MaybeAsASCII();
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (save_gen) {
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath img_fail_path = generated_img_dir_.AppendASCII(
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "FAIL_" + ref_img_filename);
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!WritePNGFile(gen_bmp, img_fail_path)) {
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(ERROR) << "Can't save generated image to: "
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << img_fail_path.value();
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(INFO) << "Saved generated image to: "
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  << img_fail_path.value();
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (save_diff) {
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath img_diff_path = generated_img_dir_.AppendASCII(
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "DIFF_" + ref_img_filename);
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!WritePNGFile(diff_bmp, img_diff_path)) {
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(ERROR) << "Can't save generated diff image to: "
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   << img_diff_path.value();
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(INFO) << "Saved difference image to: "
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  << img_diff_path.value();
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rt;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ComparePixels(const SkBitmap& gen_bmp,
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     const ReferencePixel* ref_pixels,
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     size_t ref_pixel_count) {
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkAutoLockPixels lock_bmp(gen_bmp);
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < ref_pixel_count; ++i) {
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int x = ref_pixels[i].x;
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int y = ref_pixels[i].y;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned char r = ref_pixels[i].r;
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned char g = ref_pixels[i].g;
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned char b = ref_pixels[i].b;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(x >= 0 && x < gen_bmp.width() && y >= 0 && y < gen_bmp.height());
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned char* rgba = reinterpret_cast<unsigned char*>(
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          gen_bmp.getAddr32(x, y));
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(rgba);
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rgba[0] != b || rgba[1] != g || rgba[2] != r) {
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::string error_message = base::StringPrintf(
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "pixel(%d,%d) expects [%u,%u,%u], but gets [%u,%u,%u] instead",
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            x, y, r, g, b, rgba[0], rgba[1], rgba[2]);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        LOG(ERROR) << error_message.c_str();
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return false;
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Take snapshot of the tab, encode it as PNG, and save to a SkBitmap.
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool TabSnapShotToImage(SkBitmap* bitmap, const gfx::Size& size) {
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(bitmap);
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<unsigned char> png;
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect snapshot_bounds(size);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RenderViewHost* view_host = shell()->web_contents()->GetRenderViewHost();
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!ui::GrabViewSnapshot(view_host->GetView()->GetNativeView(),
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              &png, snapshot_bounds)) {
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "ui::GrabViewSnapShot() failed";
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&*png.begin()),
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               png.size(), bitmap)) {
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Decode PNG to a SkBitmap failed";
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If no valid local revision file is located, the ref_img_revision_ is 0.
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ObtainLocalRefImageRevision() {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath filter;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    filter = filter.AppendASCII(test_name_ + "_*.rev");
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::FileEnumerator locator(ref_img_dir_,
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 false,  // non recursive
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 base::FileEnumerator::FILES,
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 filter.value());
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 max_revision = 0;
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<base::FilePath> outdated_revs;
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (base::FilePath full_path = locator.Next();
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         !full_path.empty();
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         full_path = locator.Next()) {
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string filename =
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          full_path.BaseName().RemoveExtension().MaybeAsASCII();
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string revision_string =
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          filename.substr(test_name_.length() + 1);
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int64 revision = 0;
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool converted = base::StringToInt64(revision_string, &revision);
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!converted)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (revision < ref_img_revision_no_older_than_ ||
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          revision < max_revision) {
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        outdated_revs.push_back(full_path);
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue;
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_revision = revision;
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ref_img_revision_ = max_revision;
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < outdated_revs.size(); ++i)
4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::DeleteFile(outdated_revs[i], false);
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GpuPixelBrowserTest);
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(GpuPixelBrowserTest, MANUAL_WebGLGreenTriangle) {
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If test baseline needs to be updated after a given revision, update the
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // following number. If no revision requirement, then 0.
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int64 ref_img_revision_update = 123489;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ReferencePixel ref_pixels[] = {
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // x, y, r, g, b
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {50, 100, 0, 0, 0},
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {100, 100, 0, 255, 0},
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {150, 100, 0, 0, 0},
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {50, 150, 0, 255, 0},
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {100, 150, 0, 255, 0},
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {150, 150, 0, 255, 0}
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size container_size(400, 300);
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath url =
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_data_dir().AppendASCII("pixel_webgl.html");
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunPixelTest(container_size, url, ref_img_revision_update,
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               ref_pixels, ref_pixel_count);
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(GpuPixelBrowserTest, MANUAL_CSS3DBlueBox) {
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If test baseline needs to be updated after a given revision, update the
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // following number. If no revision requirement, then 0.
464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 ref_img_revision_update = 209827;
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ReferencePixel ref_pixels[] = {
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // x, y, r, g, b
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {70, 50, 0, 0, 255},
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {150, 50, 0, 0, 0},
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {70, 90, 0, 0, 255},
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {150, 90, 0, 0, 255},
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {70, 125, 0, 0, 255},
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {150, 125, 0, 0, 0}
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size container_size(400, 300);
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath url =
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_data_dir().AppendASCII("pixel_css3d.html");
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunPixelTest(container_size, url, ref_img_revision_update,
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               ref_pixels, ref_pixel_count);
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(GpuPixelBrowserTest, MANUAL_Canvas2DRedBoxHD) {
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If test baseline needs to be updated after a given revision, update the
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // following number. If no revision requirement, then 0.
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int64 ref_img_revision_update = 123489;
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ReferencePixel ref_pixels[] = {
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // x, y, r, g, b
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {40, 100, 0, 0, 0},
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {60, 100, 127, 0, 0},
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {140, 100, 127, 0, 0},
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {160, 100, 0, 0, 0}
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size container_size(400, 300);
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath url =
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_data_dir().AppendASCII("pixel_canvas2d.html");
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunPixelTest(container_size, url, ref_img_revision_update,
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               ref_pixels, ref_pixel_count);
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GpuPixelTestCanvas2DSD : public GpuPixelBrowserTest {
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuPixelBrowserTest::SetUpCommandLine(command_line);
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(GpuPixelTestCanvas2DSD, MANUAL_Canvas2DRedBoxSD) {
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If test baseline needs to be updated after a given revision, update the
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // following number. If no revision requirement, then 0.
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int64 ref_img_revision_update = 123489;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ReferencePixel ref_pixels[] = {
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // x, y, r, g, b
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {40, 100, 0, 0, 0},
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {60, 100, 127, 0, 0},
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {140, 100, 127, 0, 0},
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {160, 100, 0, 0, 0}
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size container_size(400, 300);
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath url =
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_data_dir().AppendASCII("pixel_canvas2d.html");
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunPixelTest(container_size, url, ref_img_revision_update,
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               ref_pixels, ref_pixel_count);
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class GpuPixelTestBrowserPlugin : public GpuPixelBrowserTest {
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuPixelBrowserTest::SetUpCommandLine(command_line);
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    command_line->AppendSwitch(switches::kEnableBrowserPluginForAllViewTypes);
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// TODO(fsamuel): re-enable as MANUAL_BrowserPluginBlueBox: crbug.com/166165
543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochIN_PROC_BROWSER_TEST_F(GpuPixelTestBrowserPlugin,
544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                       DISABLED_BrowserPluginBlueBox) {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If test baseline needs to be updated after a given revision, update the
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // following number. If no revision requirement, then 0.
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int64 ref_img_revision_update = 209445;
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ReferencePixel ref_pixels[] = {
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // x, y, r, g, b
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {70, 50, 0, 0, 255},
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {150, 50, 0, 0, 0},
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {70, 90, 0, 0, 255},
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {150, 90, 0, 0, 255},
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {70, 125, 0, 0, 255},
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {150, 125, 0, 0, 0}
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t ref_pixel_count = sizeof(ref_pixels) / sizeof(ReferencePixel);
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size container_size(400, 300);
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath url =
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_data_dir().AppendASCII("pixel_browser_plugin.html");
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunPixelTest(container_size, url, ref_img_revision_update,
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               ref_pixels, ref_pixel_count);
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
569