15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/login/screenshot_tester.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ash/shell.h"
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/base_export.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/bind_internal.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/command_line.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h"
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/weak_ptr.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/prefs/pref_service.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/run_loop.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/browser_process.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/common/pref_names.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chromeos/chromeos_switches.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h"
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/compositor/compositor_switches.h"
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/image/image.h"
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/snapshot/snapshot.h"
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Sets test mode for screenshot testing.
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kTestMode[] = "test";
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Sets update mode for screenshot testing.
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kUpdateMode[] = "update";
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace chromeos {
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ScreenshotTester::ScreenshotTester() : test_mode_(false), weak_factory_(this) {
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ScreenshotTester::~ScreenshotTester() {
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ScreenshotTester::TryInitialize() {
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CommandLine& command_line = *CommandLine::ForCurrentProcess();
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!command_line.HasSwitch(switches::kEnableScreenshotTestingWithMode))
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!command_line.HasSwitch(::switches::kEnablePixelOutputInTests) ||
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !command_line.HasSwitch(::switches::kUIEnableImplSidePainting)) {
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // TODO(elizavetai): make turning on --enable-pixel-output-in-tests
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // and --ui-enable-impl-side-painting automatical.
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "--enable-pixel-output-in-tests and "
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               << "--ui-enable-impl-side-painting are required to take "
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               << "screenshots";
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string mode = command_line.GetSwitchValueASCII(
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      switches::kEnableScreenshotTestingWithMode);
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (mode != kUpdateMode && mode != kTestMode) {
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(false) << "Invalid mode for screenshot testing: " << mode;
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!command_line.HasSwitch(chromeos::switches::kGoldenScreenshotsDir)) {
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(false) << "No directory for golden screenshots specified";
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  golden_screenshots_dir_ =
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      command_line.GetSwitchValuePath(switches::kGoldenScreenshotsDir);
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (mode == kTestMode) {
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    test_mode_ = true;
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!command_line.HasSwitch(switches::kArtifactsDir)) {
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      artifacts_dir_ = golden_screenshots_dir_;
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LOG(WARNING)
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          << "No directory for artifact storing specified. Artifacts will be"
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          << "saved at golden screenshots directory.";
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else {
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      artifacts_dir_ = command_line.GetSwitchValuePath(switches::kArtifactsDir);
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ScreenshotTester::Run(const std::string& test_name) {
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  test_name_ = test_name;
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PNGFile current_screenshot = TakeScreenshot();
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (test_mode_) {
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    PNGFile golden_screenshot = LoadGoldenScreenshot();
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VLOG(0) << "Loaded golden screenshot";
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CompareScreenshots(golden_screenshot, current_screenshot);
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UpdateGoldenScreenshot(current_screenshot);
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ScreenshotTester::UpdateGoldenScreenshot(PNGFile png_data) {
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK(SaveImage("golden_screenshot", golden_screenshots_dir_, png_data));
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ScreenshotTester::SaveImage(const std::string& file_name,
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 const base::FilePath& screenshot_dir,
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 PNGFile png_data) {
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::FilePath screenshot_path =
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      screenshot_dir.AppendASCII(test_name_ + "_" + file_name + ".png");
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!png_data.get()) {
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Can't take a screenshot";
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!base::CreateDirectory(screenshot_path.DirName())) {
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Can't create a directory "
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               << screenshot_path.DirName().value();
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (static_cast<size_t>(
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::WriteFile(screenshot_path,
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          reinterpret_cast<char*>(&(png_data->data()[0])),
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          png_data->size())) != png_data->size()) {
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Can't save screenshot " << file_name;
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  VLOG(0) << "Screenshot " << file_name << ".png saved successfully to "
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          << screenshot_dir.value();
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ScreenshotTester::ReturnScreenshot(const PNGFile& screenshot,
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        PNGFile png_data) {
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  screenshot->data() = png_data->data();
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::BrowserThread::PostTask(
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content::BrowserThread::UI, FROM_HERE, run_loop_quitter_);
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ScreenshotTester::PNGFile ScreenshotTester::TakeScreenshot() {
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  aura::Window* primary_window = ash::Shell::GetPrimaryRootWindow();
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Rect rect = primary_window->bounds();
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PNGFile screenshot = new base::RefCountedBytes;
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui::GrabWindowSnapshotAsync(primary_window,
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              rect,
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              content::BrowserThread::GetBlockingPool(),
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                              base::Bind(&ScreenshotTester::ReturnScreenshot,
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         weak_factory_.GetWeakPtr(),
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         screenshot));
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::RunLoop run_loop;
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run_loop_quitter_ = run_loop.QuitClosure();
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run_loop.Run();
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return screenshot;
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ScreenshotTester::PNGFile ScreenshotTester::LoadGoldenScreenshot() {
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::FilePath screenshot_path = golden_screenshots_dir_.AppendASCII(
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      test_name_ + "_golden_screenshot.png");
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!base::PathExists(screenshot_path)) {
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(false) << "Can't find a golden screenshot for this test";
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int64 golden_screenshot_size;
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::GetFileSize(screenshot_path, &golden_screenshot_size);
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (golden_screenshot_size == -1) {
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(false) << "Can't get golden screenshot size";
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  PNGFile png_data = new base::RefCountedBytes;
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  png_data->data().resize(golden_screenshot_size);
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::ReadFile(screenshot_path,
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 reinterpret_cast<char*>(&(png_data->data()[0])),
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 golden_screenshot_size);
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return png_data;
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ScreenshotTester::CompareScreenshots(PNGFile model, PNGFile sample) {
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(model.get());
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(sample.get());
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SkBitmap model_bitmap;
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SkBitmap sample_bitmap;
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&(model->data()[0])),
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        model->data().size(),
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        &model_bitmap);
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&(sample->data()[0])),
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        sample->data().size(),
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        &sample_bitmap);
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(model_bitmap.width(), sample_bitmap.width());
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_EQ(model_bitmap.height(), sample_bitmap.height());
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool screenshots_match = true;
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SkCanvas diff_canvas(sample_bitmap);
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (int i = 0; i < model_bitmap.width(); i++)
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (int j = 0; j < model_bitmap.height(); j++) {
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (model_bitmap.getColor(i, j) == sample_bitmap.getColor(i, j)) {
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        diff_canvas.drawPoint(i, j, SK_ColorWHITE);
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      } else {
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        screenshots_match = false;
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        diff_canvas.drawPoint(i, j, SK_ColorRED);
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!screenshots_match) {
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(SaveImage("failed_screenshot", artifacts_dir_, sample));
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gfx::PNGCodec::EncodeBGRASkBitmap(sample_bitmap, false, &sample->data());
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CHECK(SaveImage("difference", artifacts_dir_, sample));
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR)
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        << "Screenshots testing failed. Screenshots differ in some pixels";
2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VLOG(0) << "Current screenshot and diff picture saved to "
2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            << artifacts_dir_.value();
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    VLOG(0) << "Current screenshot matches the golden screenshot. Screenshot "
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               "testing passed.";
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ASSERT_TRUE(screenshots_match);
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace chromeos
225