Chromium Code Reviews| Index: ash/desktop_background/desktop_background_controller_unittest.cc |
| diff --git a/ash/desktop_background/desktop_background_controller_unittest.cc b/ash/desktop_background/desktop_background_controller_unittest.cc |
| index d513a9cac7c106e80978c7be178e9994d9375935..4c8adcc721441ee784381ba95566f5a116c09f3b 100644 |
| --- a/ash/desktop_background/desktop_background_controller_unittest.cc |
| +++ b/ash/desktop_background/desktop_background_controller_unittest.cc |
| @@ -4,17 +4,35 @@ |
| #include "ash/desktop_background/desktop_background_controller.h" |
| +#include <cmath> |
| +#include <cstdlib> |
| + |
| +#include "ash/ash_switches.h" |
| +#include "ash/desktop_background/desktop_background_controller_observer.h" |
| #include "ash/desktop_background/desktop_background_widget_controller.h" |
| #include "ash/shell.h" |
| #include "ash/shell_window_ids.h" |
| #include "ash/test/ash_test_base.h" |
| +#include "ash/test/display_manager_test_api.h" |
| +#include "base/command_line.h" |
| +#include "base/file_util.h" |
| +#include "base/files/file_path.h" |
| +#include "base/files/scoped_temp_dir.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "content/public/test/test_browser_thread.h" |
| +#include "third_party/skia/include/core/SkBitmap.h" |
| +#include "third_party/skia/include/core/SkColor.h" |
| #include "ui/aura/root_window.h" |
| #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
| #include "ui/compositor/test/layer_animator_test_controller.h" |
| +#include "ui/gfx/codec/jpeg_codec.h" |
| using aura::RootWindow; |
| using aura::Window; |
| +namespace ash { |
| +namespace internal { |
| + |
| namespace { |
| // Containers IDs used for tests. |
| @@ -30,6 +48,31 @@ int ChildCountForContainer(int container_id) { |
| return static_cast<int>(container->children().size()); |
| } |
| +class TestObserver : public DesktopBackgroundControllerObserver { |
| + public: |
| + explicit TestObserver(DesktopBackgroundController* controller) |
| + : controller_(controller) { |
| + DCHECK(controller_); |
| + controller_->AddObserver(this); |
| + } |
| + |
| + virtual ~TestObserver() { |
| + controller_->RemoveObserver(this); |
| + } |
| + |
| + void WaitForWallpaperDataChanged() { |
| + base::MessageLoop::current()->Run(); |
| + } |
| + |
| + // DesktopBackgroundControllerObserver overrides: |
| + virtual void OnWallpaperDataChanged() OVERRIDE { |
| + base::MessageLoop::current()->Quit(); |
| + } |
| + |
| + private: |
| + DesktopBackgroundController* controller_; |
| +}; |
| + |
| // Steps a widget's layer animation until it is completed. Animations must be |
| // enabled. |
| void RunAnimationForWidget(views::Widget* widget) { |
| @@ -51,12 +94,11 @@ void RunAnimationForWidget(views::Widget* widget) { |
| } // namespace |
| -namespace ash { |
| -namespace internal { |
| - |
| class DesktopBackgroundControllerTest : public test::AshTestBase { |
| public: |
| - DesktopBackgroundControllerTest() {} |
| + DesktopBackgroundControllerTest() |
| + : ui_thread_(content::BrowserThread::UI, base::MessageLoop::current()) { |
| + } |
| virtual ~DesktopBackgroundControllerTest() {} |
| virtual void SetUp() OVERRIDE { |
| @@ -70,7 +112,85 @@ class DesktopBackgroundControllerTest : public test::AshTestBase { |
| static_cast<AnimatingDesktopController*>(NULL)); |
| } |
| + protected: |
| + // Runs kAnimatingDesktopController's animation to completion. |
| + // TODO(bshe): Don't require tests to run animations; it's slow. |
| + void RunDesktopControllerAnimation() { |
| + RootWindow* root = Shell::GetPrimaryRootWindow(); |
| + DesktopBackgroundWidgetController* controller = |
| + root->GetProperty(kAnimatingDesktopController)->GetController(false); |
| + ASSERT_NO_FATAL_FAILURE(RunAnimationForWidget(controller->widget())); |
| + } |
| + |
| + // Returns true if |image|'s color at (0, 0) is close to |expected_color|. |
| + bool ImageIsNearColor(gfx::ImageSkia image, SkColor expected_color) { |
| + if (image.size().IsEmpty()) { |
| + LOG(ERROR) << "Image is empty"; |
| + return false; |
| + } |
| + |
| + const SkBitmap* bitmap = image.bitmap(); |
| + if (!bitmap) { |
| + LOG(ERROR) << "Unable to get bitmap from image"; |
| + return false; |
| + } |
| + |
| + bitmap->lockPixels(); |
| + SkColor image_color = bitmap->getColor(0, 0); |
| + bitmap->unlockPixels(); |
| + |
| + const int kDiff = 3; |
| + if (std::abs(static_cast<int>(SkColorGetA(image_color)) - |
| + static_cast<int>(SkColorGetA(expected_color))) > kDiff || |
| + std::abs(static_cast<int>(SkColorGetR(image_color)) - |
| + static_cast<int>(SkColorGetR(expected_color))) > kDiff || |
| + std::abs(static_cast<int>(SkColorGetG(image_color)) - |
| + static_cast<int>(SkColorGetG(expected_color))) > kDiff || |
| + std::abs(static_cast<int>(SkColorGetB(image_color)) - |
| + static_cast<int>(SkColorGetB(expected_color))) > kDiff) { |
| + LOG(ERROR) << "Expected color near 0x" << std::hex << expected_color |
| + << " but got 0x" << image_color; |
| + return false; |
| + } |
| + |
| + return true; |
| + } |
| + |
| + // Writes a JPEG image of the specified size and color to |path|. Returns |
| + // true on success. |
| + bool WriteJPEGFile(const base::FilePath& path, |
| + int width, |
| + int height, |
| + SkColor color) { |
| + SkBitmap bitmap; |
| + bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0); |
| + bitmap.allocPixels(); |
| + bitmap.eraseColor(color); |
| + |
| + const int kQuality = 80; |
| + std::vector<unsigned char> output; |
| + if (!gfx::JPEGCodec::Encode( |
| + static_cast<const unsigned char*>(bitmap.getPixels()), |
| + gfx::JPEGCodec::FORMAT_SkBitmap, width, height, bitmap.rowBytes(), |
| + kQuality, &output)) { |
| + LOG(ERROR) << "Unable to encode " << width << "x" << height << " bitmap"; |
| + return false; |
| + } |
| + |
| + size_t bytes_written = file_util::WriteFile( |
| + path, reinterpret_cast<const char*>(&output[0]), output.size()); |
| + if (bytes_written != output.size()) { |
| + LOG(ERROR) << "Wrote " << bytes_written << " byte(s) instead of " |
| + << output.size() << " to " << path.value(); |
| + return false; |
| + } |
| + |
| + return true; |
| + } |
| + |
| private: |
| + content::TestBrowserThread ui_thread_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(DesktopBackgroundControllerTest); |
| }; |
| @@ -123,10 +243,7 @@ TEST_F(DesktopBackgroundControllerTest, ControllerOwnership) { |
| EXPECT_FALSE(root->GetProperty(kDesktopController)); |
| // Force the widget's layer animation to play to completion. |
| - ASSERT_NO_FATAL_FAILURE( |
| - RunAnimationForWidget( |
| - root->GetProperty(kAnimatingDesktopController)->GetController(false)-> |
| - widget())); |
| + RunDesktopControllerAnimation(); |
| // Ownership has moved from kAnimatingDesktopController to kDesktopController. |
| EXPECT_FALSE( |
| @@ -147,11 +264,7 @@ TEST_F(DesktopBackgroundControllerTest, BackgroundMovementDuringUnlock) { |
| controller->CreateEmptyWallpaper(); |
| // Run wallpaper show animation to completion. |
| - RootWindow* root = Shell::GetPrimaryRootWindow(); |
| - ASSERT_NO_FATAL_FAILURE( |
| - RunAnimationForWidget( |
| - root->GetProperty(kAnimatingDesktopController)->GetController(false)-> |
| - widget())); |
| + RunDesktopControllerAnimation(); |
| // User locks the screen, which moves the background forward. |
| controller->MoveDesktopToLockedContainer(); |
| @@ -162,6 +275,7 @@ TEST_F(DesktopBackgroundControllerTest, BackgroundMovementDuringUnlock) { |
| // In this state we have two desktop background views stored in different |
| // properties. Both are in the lock screen background container. |
| + RootWindow* root = Shell::GetPrimaryRootWindow(); |
| EXPECT_TRUE( |
| root->GetProperty(kAnimatingDesktopController)->GetController(false)); |
| EXPECT_TRUE(root->GetProperty(kDesktopController)); |
| @@ -177,10 +291,7 @@ TEST_F(DesktopBackgroundControllerTest, BackgroundMovementDuringUnlock) { |
| EXPECT_EQ(0, ChildCountForContainer(kLockScreenBackgroundId)); |
| // Finish the new desktop background animation. |
| - ASSERT_NO_FATAL_FAILURE( |
| - RunAnimationForWidget( |
| - root->GetProperty(kAnimatingDesktopController)->GetController(false)-> |
| - widget())); |
| + RunDesktopControllerAnimation(); |
| // Now there is one desktop background, in the back. |
| EXPECT_EQ(1, ChildCountForContainer(kDesktopBackgroundId)); |
| @@ -200,28 +311,25 @@ TEST_F(DesktopBackgroundControllerTest, ChangeWallpaperQuick) { |
| controller->CreateEmptyWallpaper(); |
| // Run wallpaper show animation to completion. |
| - RootWindow* root = Shell::GetPrimaryRootWindow(); |
| - ASSERT_NO_FATAL_FAILURE( |
| - RunAnimationForWidget( |
| - root->GetProperty(kAnimatingDesktopController)->GetController(false)-> |
| - widget())); |
| + RunDesktopControllerAnimation(); |
| // Change to a new wallpaper. |
| controller->CreateEmptyWallpaper(); |
| - DesktopBackgroundWidgetController* animatingController = |
| + RootWindow* root = Shell::GetPrimaryRootWindow(); |
| + DesktopBackgroundWidgetController* animating_controller = |
| root->GetProperty(kAnimatingDesktopController)->GetController(false); |
| - EXPECT_TRUE(animatingController); |
| + EXPECT_TRUE(animating_controller); |
| EXPECT_TRUE(root->GetProperty(kDesktopController)); |
| // Change to another wallpaper before animation finished. |
| controller->CreateEmptyWallpaper(); |
| // The animating controller should immediately move to desktop controller. |
| - EXPECT_EQ(animatingController, root->GetProperty(kDesktopController)); |
| + EXPECT_EQ(animating_controller, root->GetProperty(kDesktopController)); |
| // Cache the new animating controller. |
| - animatingController = |
| + animating_controller = |
| root->GetProperty(kAnimatingDesktopController)->GetController(false); |
| // Run wallpaper show animation to completion. |
| @@ -234,7 +342,92 @@ TEST_F(DesktopBackgroundControllerTest, ChangeWallpaperQuick) { |
| EXPECT_FALSE( |
| root->GetProperty(kAnimatingDesktopController)->GetController(false)); |
| // The desktop controller should be the last created animating controller. |
| - EXPECT_EQ(animatingController, root->GetProperty(kDesktopController)); |
| + EXPECT_EQ(animating_controller, root->GetProperty(kDesktopController)); |
| +} |
| + |
| +// Tests that SetDefaultWallpaper() loads default wallpaper from disk when |
| +// instructed to do so via command-line flags. |
| +TEST_F(DesktopBackgroundControllerTest, SetDefaultWallpaper) { |
| + // We cannot short-circuit animations for this test. |
| + ui::ScopedAnimationDurationScaleMode normal_duration_mode( |
| + ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); |
| + |
| + DesktopBackgroundController* controller = |
| + Shell::GetInstance()->desktop_background_controller(); |
| + TestObserver observer(controller); |
| + |
| + base::ScopedTempDir temp_dir; |
| + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| + |
| + const base::FilePath kLargePath = |
| + temp_dir.path().Append(FILE_PATH_LITERAL("large.jpg")); |
| + const SkColor kLargeColor = SK_ColorRED; |
| + ASSERT_TRUE(WriteJPEGFile(kLargePath, kLargeWallpaperMaxWidth, |
| + kLargeWallpaperMaxHeight, kLargeColor)); |
| + |
| + const base::FilePath kSmallPath = |
| + temp_dir.path().Append(FILE_PATH_LITERAL("small.jpg")); |
| + const SkColor kSmallColor = SK_ColorGREEN; |
| + ASSERT_TRUE(WriteJPEGFile(kSmallPath, kSmallWallpaperMaxWidth, |
| + kSmallWallpaperMaxHeight, kSmallColor)); |
| + |
| + const base::FilePath kLargeGuestPath = |
| + temp_dir.path().Append(FILE_PATH_LITERAL("guest_large.jpg")); |
| + const SkColor kLargeGuestColor = SK_ColorBLUE; |
| + ASSERT_TRUE(WriteJPEGFile(kLargeGuestPath, kLargeWallpaperMaxWidth, |
| + kLargeWallpaperMaxHeight, kLargeGuestColor)); |
| + |
| + const base::FilePath kSmallGuestPath = |
| + temp_dir.path().Append(FILE_PATH_LITERAL("guest_small.jpg")); |
| + const SkColor kSmallGuestColor = SK_ColorYELLOW; |
| + ASSERT_TRUE(WriteJPEGFile(kSmallGuestPath, kSmallWallpaperMaxWidth, |
| + kSmallWallpaperMaxHeight, kSmallGuestColor)); |
| + |
| + CommandLine command_line(CommandLine::NO_PROGRAM); |
| + command_line.AppendSwitchPath( |
| + switches::kAshDefaultWallpaperLarge, kLargePath); |
| + command_line.AppendSwitchPath( |
| + switches::kAshDefaultWallpaperSmall, kSmallPath); |
| + command_line.AppendSwitchPath( |
| + switches::kAshDefaultGuestWallpaperLarge, kLargeGuestPath); |
| + command_line.AppendSwitchPath( |
| + switches::kAshDefaultGuestWallpaperSmall, kSmallGuestPath); |
| + controller->set_command_line_for_testing(&command_line); |
| + |
| + // At 800x600, the small wallpaper should be loaded. |
| + test::DisplayManagerTestApi display_manager_test_api( |
| + Shell::GetInstance()->display_manager()); |
| + display_manager_test_api.UpdateDisplay("800x600"); |
| + ASSERT_TRUE(controller->SetDefaultWallpaper(false)); |
| + observer.WaitForWallpaperDataChanged(); |
| + RunDesktopControllerAnimation(); |
| + EXPECT_TRUE(ImageIsNearColor(controller->GetWallpaper(), kSmallColor)); |
| + |
| + // Requesting the same wallpaper again should be a no-op. |
| + EXPECT_FALSE(controller->SetDefaultWallpaper(false)); |
| + |
| + // It should still be a no-op after adding a second small display (i.e. |
| + // the controller should continue using the same wallpaper). |
| + display_manager_test_api.UpdateDisplay("800x600,800x600"); |
| + EXPECT_FALSE(controller->SetDefaultWallpaper(false)); |
| + |
| + // Switch to guest mode and check that the small guest wallpaper is loaded. |
| + ASSERT_TRUE(controller->SetDefaultWallpaper(true)); |
| + observer.WaitForWallpaperDataChanged(); |
|
bshe
2013/06/21 00:43:14
Your new test if still good.
For the old test, I j
Daniel Erat
2013/06/21 00:53:31
Yeah, I noticed this too when I was updating the t
|
| + EXPECT_TRUE(ImageIsNearColor(controller->GetWallpaper(), kSmallGuestColor)); |
| + |
| + // Switch to a larger display and check that the large wallpaper is loaded. |
| + display_manager_test_api.UpdateDisplay("1600x1200"); |
| + ASSERT_TRUE(controller->SetDefaultWallpaper(false)); |
| + observer.WaitForWallpaperDataChanged(); |
| + RunDesktopControllerAnimation(); |
| + EXPECT_TRUE(ImageIsNearColor(controller->GetWallpaper(), kLargeColor)); |
| + |
| + // Switch to the guest wallpaper while still at a higher resolution. |
| + ASSERT_TRUE(controller->SetDefaultWallpaper(true)); |
| + observer.WaitForWallpaperDataChanged(); |
| + RunDesktopControllerAnimation(); |
| + EXPECT_TRUE(ImageIsNearColor(controller->GetWallpaper(), kLargeGuestColor)); |
| } |
| } // namespace internal |