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