Index: chrome/browser/chromeos/login/screenshot_tester.cc |
diff --git a/chrome/browser/chromeos/login/screenshot_tester.cc b/chrome/browser/chromeos/login/screenshot_tester.cc |
index 683f987d6d0f82c460edeaf1d1ef6841bf16722d..cfc4cf2da83b972eb569186c63ed0727bc8ec1a2 100644 |
--- a/chrome/browser/chromeos/login/screenshot_tester.cc |
+++ b/chrome/browser/chromeos/login/screenshot_tester.cc |
@@ -8,6 +8,7 @@ |
#include "base/base_export.h" |
#include "base/bind_internal.h" |
#include "base/command_line.h" |
+#include "base/logging.h" |
#include "base/memory/weak_ptr.h" |
#include "base/prefs/pref_service.h" |
#include "base/run_loop.h" |
@@ -15,13 +16,27 @@ |
#include "chrome/common/pref_names.h" |
#include "chromeos/chromeos_switches.h" |
#include "content/public/browser/browser_thread.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
+#include "third_party/skia/include/core/SkCanvas.h" |
#include "ui/compositor/compositor_switches.h" |
+#include "ui/gfx/codec/png_codec.h" |
#include "ui/gfx/image/image.h" |
#include "ui/snapshot/snapshot.h" |
+namespace { |
+ |
+// Sets test mode for screenshot testing. |
+const char kTestMode[] = "test"; |
+ |
+// Sets update mode for screenshot testing. |
+const char kUpdateMode[] = "update"; |
+ |
+} // namespace |
+ |
namespace chromeos { |
-ScreenshotTester::ScreenshotTester() : weak_factory_(this) { |
+ScreenshotTester::ScreenshotTester() : test_mode_(false), weak_factory_(this) { |
} |
ScreenshotTester::~ScreenshotTester() { |
@@ -29,7 +44,7 @@ ScreenshotTester::~ScreenshotTester() { |
bool ScreenshotTester::TryInitialize() { |
CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
- if (!command_line.HasSwitch(switches::kEnableScreenshotTesting)) |
+ if (!command_line.HasSwitch(switches::kEnableScreenshotTestingWithMode)) |
return false; |
if (!command_line.HasSwitch(::switches::kEnablePixelOutputInTests) || |
!command_line.HasSwitch(::switches::kUIEnableImplSidePainting)) { |
@@ -40,64 +55,170 @@ bool ScreenshotTester::TryInitialize() { |
<< "screenshots"; |
return false; |
} |
- if (!command_line.HasSwitch(switches::kScreenshotDestinationDir)) { |
- LOG(ERROR) << "No destination for screenshots specified"; |
- return false; |
+ |
+ std::string mode = command_line.GetSwitchValueASCII( |
+ switches::kEnableScreenshotTestingWithMode); |
+ if (mode != kUpdateMode && mode != kTestMode) { |
+ CHECK(false) << "Invalid mode for screenshot testing: " << mode; |
+ } |
+ |
+ if (!command_line.HasSwitch(chromeos::switches::kGoldenScreenshotsDir)) { |
+ CHECK(false) << "No directory for golden screenshots specified"; |
+ } |
+ |
+ golden_screenshots_dir_ = |
+ command_line.GetSwitchValuePath(switches::kGoldenScreenshotsDir); |
+ |
+ if (mode == kTestMode) { |
+ test_mode_ = true; |
+ if (!command_line.HasSwitch(switches::kArtifactsDir)) { |
+ artifacts_dir_ = golden_screenshots_dir_; |
+ LOG(WARNING) |
+ << "No directory for artifact storing specified. Artifacts will be" |
+ << "saved at golden screenshots directory."; |
+ } else { |
+ artifacts_dir_ = command_line.GetSwitchValuePath(switches::kArtifactsDir); |
+ } |
} |
- screenshot_dest_ = command_line.GetSwitchValuePath( |
- chromeos::switches::kScreenshotDestinationDir); |
return true; |
} |
-void ScreenshotTester::Run(const std::string& file_name) { |
- TakeScreenshot(); |
- PNGFile current_screenshot = screenshot_; |
- UpdateGoldenScreenshot(file_name, current_screenshot); |
+void ScreenshotTester::Run(const std::string& test_name) { |
+ test_name_ = test_name; |
+ PNGFile current_screenshot = TakeScreenshot(); |
+ if (test_mode_) { |
+ PNGFile golden_screenshot = LoadGoldenScreenshot(); |
+ VLOG(0) << "Loaded golden screenshot"; |
+ CompareScreenshots(golden_screenshot, current_screenshot); |
+ } else { |
+ UpdateGoldenScreenshot(current_screenshot); |
+ } |
} |
-void ScreenshotTester::UpdateGoldenScreenshot(const std::string& file_name, |
- PNGFile png_data) { |
+void ScreenshotTester::UpdateGoldenScreenshot(PNGFile png_data) { |
+ CHECK(SaveImage("golden_screenshot", golden_screenshots_dir_, png_data)); |
+} |
+ |
+bool ScreenshotTester::SaveImage(const std::string& file_name, |
+ const base::FilePath& screenshot_dir, |
+ PNGFile png_data) { |
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ base::FilePath screenshot_path = |
+ screenshot_dir.AppendASCII(test_name_ + "_" + file_name + ".png"); |
if (!png_data) { |
LOG(ERROR) << "Can't take a screenshot"; |
- return; |
+ return false; |
} |
- base::FilePath golden_screenshot_path = |
- screenshot_dest_.AppendASCII(file_name + ".png"); |
- if (!base::CreateDirectory(golden_screenshot_path.DirName())) { |
- LOG(ERROR) << "Can't create a directory "; |
- return; |
+ if (!base::CreateDirectory(screenshot_path.DirName())) { |
+ LOG(ERROR) << "Can't create a directory " |
+ << screenshot_path.DirName().value(); |
+ return false; |
} |
if (static_cast<size_t>( |
- base::WriteFile(golden_screenshot_path, |
+ base::WriteFile(screenshot_path, |
reinterpret_cast<char*>(&(png_data->data()[0])), |
png_data->size())) != png_data->size()) { |
- LOG(ERROR) << "Can't save screenshot"; |
+ LOG(ERROR) << "Can't save screenshot " << file_name; |
+ return false; |
} |
- VLOG(0) << "Golden screenshot updated successfully"; |
+ VLOG(0) << "Screenshot " << file_name << ".png saved successfully to " |
+ << screenshot_dir.value(); |
+ return true; |
} |
-void ScreenshotTester::ReturnScreenshot(PNGFile png_data) { |
- // TODO(elizavetai): rewrite this function so that TakeScreenshot |
- // could return a |PNGFile| -- current screenshot. |
+void ScreenshotTester::ReturnScreenshot(const PNGFile& screenshot, |
+ PNGFile png_data) { |
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- screenshot_ = png_data; |
+ screenshot->data() = png_data->data(); |
content::BrowserThread::PostTask( |
content::BrowserThread::UI, FROM_HERE, run_loop_quitter_); |
} |
-void ScreenshotTester::TakeScreenshot() { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ScreenshotTester::PNGFile ScreenshotTester::TakeScreenshot() { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
aura::Window* primary_window = ash::Shell::GetPrimaryRootWindow(); |
gfx::Rect rect = primary_window->bounds(); |
+ PNGFile screenshot = new base::RefCountedBytes; |
ui::GrabWindowSnapshotAsync(primary_window, |
rect, |
content::BrowserThread::GetBlockingPool(), |
base::Bind(&ScreenshotTester::ReturnScreenshot, |
- weak_factory_.GetWeakPtr())); |
+ weak_factory_.GetWeakPtr(), |
+ screenshot)); |
base::RunLoop run_loop; |
run_loop_quitter_ = run_loop.QuitClosure(); |
run_loop.Run(); |
+ return screenshot; |
+} |
+ |
+ScreenshotTester::PNGFile ScreenshotTester::LoadGoldenScreenshot() { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ |
+ base::FilePath screenshot_path = golden_screenshots_dir_.AppendASCII( |
+ test_name_ + "_golden_screenshot.png"); |
+ if (!base::PathExists(screenshot_path)) { |
+ CHECK(false) << "Can't find a golden screenshot for this test"; |
+ } |
+ |
+ int64 golden_screenshot_size; |
+ base::GetFileSize(screenshot_path, &golden_screenshot_size); |
+ |
+ if (golden_screenshot_size == -1) { |
+ CHECK(false) << "Can't get golden screenshot size"; |
+ } |
+ PNGFile png_data = new base::RefCountedBytes; |
+ png_data->data().resize(golden_screenshot_size); |
+ base::ReadFile(screenshot_path, |
+ reinterpret_cast<char*>(&(png_data->data()[0])), |
+ golden_screenshot_size); |
+ |
+ return png_data; |
+} |
+ |
+void ScreenshotTester::CompareScreenshots(PNGFile model, PNGFile sample) { |
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
+ |
+ ASSERT_TRUE(model.get()); |
+ ASSERT_TRUE(sample.get()); |
+ |
+ SkBitmap model_bitmap; |
+ SkBitmap sample_bitmap; |
+ gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&(model->data()[0])), |
+ model->data().size(), |
+ &model_bitmap); |
+ gfx::PNGCodec::Decode(reinterpret_cast<unsigned char*>(&(sample->data()[0])), |
+ sample->data().size(), |
+ &sample_bitmap); |
+ |
+ ASSERT_EQ(model_bitmap.width(), sample_bitmap.width()); |
+ ASSERT_EQ(model_bitmap.height(), sample_bitmap.height()); |
+ |
+ bool screenshots_match = true; |
+ |
+ SkCanvas diff_canvas(sample_bitmap); |
+ for (int i = 0; i < model_bitmap.width(); i++) |
+ for (int j = 0; j < model_bitmap.height(); j++) { |
+ if (model_bitmap.getColor(i, j) == sample_bitmap.getColor(i, j)) { |
+ diff_canvas.drawPoint(i, j, SK_ColorWHITE); |
+ } else { |
+ screenshots_match = false; |
+ diff_canvas.drawPoint(i, j, SK_ColorRED); |
+ } |
+ } |
+ |
+ if (!screenshots_match) { |
+ CHECK(SaveImage("failed_screenshot", artifacts_dir_, sample)); |
+ gfx::PNGCodec::EncodeBGRASkBitmap(sample_bitmap, false, &sample->data()); |
+ CHECK(SaveImage("difference", artifacts_dir_, sample)); |
+ LOG(ERROR) |
+ << "Screenshots testing failed. Screenshots differ in some pixels"; |
+ VLOG(0) << "Current screenshot and diff picture saved to " |
+ << artifacts_dir_.value(); |
+ } else { |
+ VLOG(0) << "Current screenshot matches the golden screenshot. Screenshot " |
+ "testing passed."; |
+ } |
+ ASSERT_TRUE(screenshots_match); |
} |
} // namespace chromeos |