diff options
Diffstat (limited to 'chromium/ash/wm/video_detector_unittest.cc')
-rw-r--r-- | chromium/ash/wm/video_detector_unittest.cc | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/chromium/ash/wm/video_detector_unittest.cc b/chromium/ash/wm/video_detector_unittest.cc new file mode 100644 index 00000000000..01c79cf8797 --- /dev/null +++ b/chromium/ash/wm/video_detector_unittest.cc @@ -0,0 +1,295 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/video_detector.h" + +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "ash/wm/window_util.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/client/window_types.h" +#include "ui/aura/root_window.h" +#include "ui/aura/test/test_windows.h" +#include "ui/aura/window.h" +#include "ui/gfx/rect.h" + +namespace ash { +namespace test { + +// Implementation that just counts the number of times we've been told that a +// video is playing. +class TestVideoDetectorObserver : public VideoDetectorObserver { + public: + TestVideoDetectorObserver() : num_invocations_(0), + num_fullscreens_(0), + num_not_fullscreens_(0) {} + + int num_invocations() const { return num_invocations_; } + int num_fullscreens() const { return num_fullscreens_; } + int num_not_fullscreens() const { return num_not_fullscreens_; } + void reset_stats() { + num_invocations_ = 0; + num_fullscreens_ = 0; + num_not_fullscreens_ = 0; + } + + // VideoDetectorObserver implementation. + virtual void OnVideoDetected(bool is_fullscreen) OVERRIDE { + num_invocations_++; + if (is_fullscreen) + num_fullscreens_++; + else + num_not_fullscreens_++; + } + + private: + // Number of times that OnVideoDetected() has been called. + int num_invocations_; + // Number of times that OnVideoDetected() has been called with is_fullscreen + // == true. + int num_fullscreens_; + // Number of times that OnVideoDetected() has been called with is_fullscreen + // == false. + int num_not_fullscreens_; + + DISALLOW_COPY_AND_ASSIGN(TestVideoDetectorObserver); +}; + +class VideoDetectorTest : public AshTestBase { + public: + VideoDetectorTest() {} + virtual ~VideoDetectorTest() {} + + virtual void SetUp() OVERRIDE { + AshTestBase::SetUp(); + observer_.reset(new TestVideoDetectorObserver); + detector_ = Shell::GetInstance()->video_detector(); + detector_->AddObserver(observer_.get()); + + now_ = base::TimeTicks::Now(); + detector_->set_now_for_test(now_); + } + + virtual void TearDown() OVERRIDE { + detector_->RemoveObserver(observer_.get()); + AshTestBase::TearDown(); + } + + protected: + // Move |detector_|'s idea of the current time forward by |delta|. + void AdvanceTime(base::TimeDelta delta) { + now_ += delta; + detector_->set_now_for_test(now_); + } + + VideoDetector* detector_; // not owned + + scoped_ptr<TestVideoDetectorObserver> observer_; + + base::TimeTicks now_; + + private: + DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest); +}; + +TEST_F(VideoDetectorTest, Basic) { + gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); + scoped_ptr<aura::Window> window( + CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); + + // Send enough updates, but make them be too small to trigger detection. + gfx::Rect update_region( + gfx::Point(), + gfx::Size(VideoDetector::kMinUpdateWidth - 1, + VideoDetector::kMinUpdateHeight)); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(0, observer_->num_invocations()); + + // Send not-quite-enough adaquately-sized updates. + observer_->reset_stats(); + AdvanceTime(base::TimeDelta::FromSeconds(2)); + update_region.set_size( + gfx::Size(VideoDetector::kMinUpdateWidth, + VideoDetector::kMinUpdateHeight)); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(0, observer_->num_invocations()); + + // We should get notified after the next update, but not in response to + // additional updates. + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(1, observer_->num_invocations()); + EXPECT_EQ(0, observer_->num_fullscreens()); + EXPECT_EQ(1, observer_->num_not_fullscreens()); + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(1, observer_->num_invocations()); + EXPECT_EQ(0, observer_->num_fullscreens()); + EXPECT_EQ(1, observer_->num_not_fullscreens()); + + // Spread out the frames over a longer period of time, but send enough + // over a one-second window that the observer should be notified. + observer_->reset_stats(); + AdvanceTime(base::TimeDelta::FromSeconds(2)); + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(0, observer_->num_invocations()); + + AdvanceTime(base::TimeDelta::FromMilliseconds(500)); + const int kNumFrames = VideoDetector::kMinFramesPerSecond + 1; + base::TimeDelta kInterval = + base::TimeDelta::FromMilliseconds(1000 / kNumFrames); + for (int i = 0; i < kNumFrames; ++i) { + AdvanceTime(kInterval); + detector_->OnWindowPaintScheduled(window.get(), update_region); + } + EXPECT_EQ(1, observer_->num_invocations()); + + // Keep going and check that the observer is notified again. + for (int i = 0; i < kNumFrames; ++i) { + AdvanceTime(kInterval); + detector_->OnWindowPaintScheduled(window.get(), update_region); + } + EXPECT_EQ(2, observer_->num_invocations()); + + // Send updates at a slower rate and check that the observer isn't notified. + base::TimeDelta kSlowInterval = base::TimeDelta::FromMilliseconds( + 1000 / (VideoDetector::kMinFramesPerSecond - 2)); + for (int i = 0; i < kNumFrames; ++i) { + AdvanceTime(kSlowInterval); + detector_->OnWindowPaintScheduled(window.get(), update_region); + } + EXPECT_EQ(2, observer_->num_invocations()); +} + +TEST_F(VideoDetectorTest, Shutdown) { + gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); + scoped_ptr<aura::Window> window( + CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); + gfx::Rect update_region( + gfx::Point(), + gfx::Size(VideoDetector::kMinUpdateWidth, + VideoDetector::kMinUpdateHeight)); + + // It should not detect video during the shutdown. + Shell::GetInstance()->OnAppTerminating(); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(0, observer_->num_invocations()); +} + +TEST_F(VideoDetectorTest, WindowNotVisible) { + gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); + scoped_ptr<aura::Window> window( + CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); + + // Reparent the window to the root to make sure that visibility changes aren't + // animated. + Shell::GetPrimaryRootWindow()->AddChild(window.get()); + + // We shouldn't report video that's played in a hidden window. + window->Hide(); + gfx::Rect update_region( + gfx::Point(), + gfx::Size(VideoDetector::kMinUpdateWidth, + VideoDetector::kMinUpdateHeight)); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(0, observer_->num_invocations()); + + // Make the window visible and send more updates. + observer_->reset_stats(); + AdvanceTime(base::TimeDelta::FromSeconds(2)); + window->Show(); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(1, observer_->num_invocations()); + EXPECT_EQ(0, observer_->num_fullscreens()); + EXPECT_EQ(1, observer_->num_not_fullscreens()); + + // We also shouldn't report video in a window that's fully offscreen. + observer_->reset_stats(); + AdvanceTime(base::TimeDelta::FromSeconds(2)); + gfx::Rect offscreen_bounds( + gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0), + window_bounds.size()); + window->SetBounds(offscreen_bounds); + ASSERT_EQ(offscreen_bounds, window->bounds()); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(0, observer_->num_invocations()); +} + +TEST_F(VideoDetectorTest, MultipleWindows) { + // Create two windows. + gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); + scoped_ptr<aura::Window> window1( + CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); + scoped_ptr<aura::Window> window2( + CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds)); + + // Even if there's video playing in both, the observer should only receive a + // single notification. + gfx::Rect update_region( + gfx::Point(), + gfx::Size(VideoDetector::kMinUpdateWidth, + VideoDetector::kMinUpdateHeight)); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window1.get(), update_region); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window2.get(), update_region); + EXPECT_EQ(1, observer_->num_invocations()); + EXPECT_EQ(0, observer_->num_fullscreens()); + EXPECT_EQ(1, observer_->num_not_fullscreens()); +} + +// Test that the observer receives repeated notifications. +TEST_F(VideoDetectorTest, RepeatedNotifications) { + gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); + scoped_ptr<aura::Window> window( + CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); + + gfx::Rect update_region( + gfx::Point(), + gfx::Size(VideoDetector::kMinUpdateWidth, + VideoDetector::kMinUpdateHeight)); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(1, observer_->num_invocations()); + EXPECT_EQ(0, observer_->num_fullscreens()); + EXPECT_EQ(1, observer_->num_not_fullscreens()); + // Let enough time pass that a second notification should be sent. + observer_->reset_stats(); + AdvanceTime(base::TimeDelta::FromSeconds( + static_cast<int64>(VideoDetector::kNotifyIntervalSec + 1))); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(1, observer_->num_invocations()); + EXPECT_EQ(0, observer_->num_fullscreens()); + EXPECT_EQ(1, observer_->num_not_fullscreens()); +} + +// Test that the observer receives a true value when the window is fullscreen. +TEST_F(VideoDetectorTest, FullscreenWindow) { + gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); + scoped_ptr<aura::Window> window( + CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); + window->Focus(); + gfx::Rect update_region( + gfx::Point(), + gfx::Size(VideoDetector::kMinUpdateWidth, + VideoDetector::kMinUpdateHeight)); + for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) + detector_->OnWindowPaintScheduled(window.get(), update_region); + EXPECT_EQ(1, observer_->num_invocations()); + EXPECT_EQ(1, observer_->num_fullscreens()); + EXPECT_EQ(0, observer_->num_not_fullscreens()); +} + +} // namespace test +} // namespace ash |