video_detector_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ash/wm/video_detector.h" 6 7#include "ash/shell.h" 8#include "ash/test/ash_test_base.h" 9#include "ash/wm/window_util.h" 10#include "base/compiler_specific.h" 11#include "base/memory/scoped_ptr.h" 12#include "base/time.h" 13#include "third_party/skia/include/core/SkColor.h" 14#include "ui/aura/client/aura_constants.h" 15#include "ui/aura/client/window_types.h" 16#include "ui/aura/root_window.h" 17#include "ui/aura/test/test_windows.h" 18#include "ui/aura/window.h" 19#include "ui/gfx/rect.h" 20 21namespace ash { 22namespace test { 23 24// Implementation that just counts the number of times we've been told that a 25// video is playing. 26class TestVideoDetectorObserver : public VideoDetectorObserver { 27 public: 28 TestVideoDetectorObserver() : num_invocations_(0), 29 num_fullscreens_(0), 30 num_not_fullscreens_(0) {} 31 32 int num_invocations() const { return num_invocations_; } 33 int num_fullscreens() const { return num_fullscreens_; } 34 int num_not_fullscreens() const { return num_not_fullscreens_; } 35 void reset_stats() { 36 num_invocations_ = 0; 37 num_fullscreens_ = 0; 38 num_not_fullscreens_ = 0; 39 } 40 41 // VideoDetectorObserver implementation. 42 virtual void OnVideoDetected(bool is_fullscreen) OVERRIDE { 43 num_invocations_++; 44 if (is_fullscreen) 45 num_fullscreens_++; 46 else 47 num_not_fullscreens_++; 48 } 49 50 private: 51 // Number of times that OnVideoDetected() has been called. 52 int num_invocations_; 53 // Number of times that OnVideoDetected() has been called with is_fullscreen 54 // == true. 55 int num_fullscreens_; 56 // Number of times that OnVideoDetected() has been called with is_fullscreen 57 // == false. 58 int num_not_fullscreens_; 59 60 DISALLOW_COPY_AND_ASSIGN(TestVideoDetectorObserver); 61}; 62 63class VideoDetectorTest : public AshTestBase { 64 public: 65 VideoDetectorTest() {} 66 virtual ~VideoDetectorTest() {} 67 68 virtual void SetUp() OVERRIDE { 69 AshTestBase::SetUp(); 70 observer_.reset(new TestVideoDetectorObserver); 71 detector_ = Shell::GetInstance()->video_detector(); 72 detector_->AddObserver(observer_.get()); 73 74 now_ = base::TimeTicks::Now(); 75 detector_->set_now_for_test(now_); 76 } 77 78 virtual void TearDown() OVERRIDE { 79 detector_->RemoveObserver(observer_.get()); 80 AshTestBase::TearDown(); 81 } 82 83 protected: 84 // Move |detector_|'s idea of the current time forward by |delta|. 85 void AdvanceTime(base::TimeDelta delta) { 86 now_ += delta; 87 detector_->set_now_for_test(now_); 88 } 89 90 VideoDetector* detector_; // not owned 91 92 scoped_ptr<TestVideoDetectorObserver> observer_; 93 94 base::TimeTicks now_; 95 96 private: 97 DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest); 98}; 99 100TEST_F(VideoDetectorTest, Basic) { 101 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 102 scoped_ptr<aura::Window> window( 103 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 104 105 // Send enough updates, but make them be too small to trigger detection. 106 gfx::Rect update_region( 107 gfx::Point(), 108 gfx::Size(VideoDetector::kMinUpdateWidth - 1, 109 VideoDetector::kMinUpdateHeight)); 110 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 111 detector_->OnWindowPaintScheduled(window.get(), update_region); 112 EXPECT_EQ(0, observer_->num_invocations()); 113 114 // Send not-quite-enough adaquately-sized updates. 115 observer_->reset_stats(); 116 AdvanceTime(base::TimeDelta::FromSeconds(2)); 117 update_region.set_size( 118 gfx::Size(VideoDetector::kMinUpdateWidth, 119 VideoDetector::kMinUpdateHeight)); 120 for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) 121 detector_->OnWindowPaintScheduled(window.get(), update_region); 122 EXPECT_EQ(0, observer_->num_invocations()); 123 124 // We should get notified after the next update, but not in response to 125 // additional updates. 126 detector_->OnWindowPaintScheduled(window.get(), update_region); 127 EXPECT_EQ(1, observer_->num_invocations()); 128 EXPECT_EQ(0, observer_->num_fullscreens()); 129 EXPECT_EQ(1, observer_->num_not_fullscreens()); 130 detector_->OnWindowPaintScheduled(window.get(), update_region); 131 EXPECT_EQ(1, observer_->num_invocations()); 132 EXPECT_EQ(0, observer_->num_fullscreens()); 133 EXPECT_EQ(1, observer_->num_not_fullscreens()); 134 135 // Spread out the frames over two seconds; we shouldn't detect video. 136 observer_->reset_stats(); 137 AdvanceTime(base::TimeDelta::FromSeconds(2)); 138 for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) 139 detector_->OnWindowPaintScheduled(window.get(), update_region); 140 AdvanceTime(base::TimeDelta::FromSeconds(1)); 141 for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) 142 detector_->OnWindowPaintScheduled(window.get(), update_region); 143 EXPECT_EQ(0, observer_->num_invocations()); 144} 145 146TEST_F(VideoDetectorTest, Shutdown) { 147 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 148 scoped_ptr<aura::Window> window( 149 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 150 gfx::Rect update_region( 151 gfx::Point(), 152 gfx::Size(VideoDetector::kMinUpdateWidth, 153 VideoDetector::kMinUpdateHeight)); 154 155 // It should not detect video during the shutdown. 156 Shell::GetInstance()->OnAppTerminating(); 157 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 158 detector_->OnWindowPaintScheduled(window.get(), update_region); 159 EXPECT_EQ(0, observer_->num_invocations()); 160} 161 162TEST_F(VideoDetectorTest, WindowNotVisible) { 163 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 164 scoped_ptr<aura::Window> window( 165 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 166 167 // Reparent the window to the root to make sure that visibility changes aren't 168 // animated. 169 Shell::GetPrimaryRootWindow()->AddChild(window.get()); 170 171 // We shouldn't report video that's played in a hidden window. 172 window->Hide(); 173 gfx::Rect update_region( 174 gfx::Point(), 175 gfx::Size(VideoDetector::kMinUpdateWidth, 176 VideoDetector::kMinUpdateHeight)); 177 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 178 detector_->OnWindowPaintScheduled(window.get(), update_region); 179 EXPECT_EQ(0, observer_->num_invocations()); 180 181 // Make the window visible and send more updates. 182 observer_->reset_stats(); 183 AdvanceTime(base::TimeDelta::FromSeconds(2)); 184 window->Show(); 185 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 186 detector_->OnWindowPaintScheduled(window.get(), update_region); 187 EXPECT_EQ(1, observer_->num_invocations()); 188 EXPECT_EQ(0, observer_->num_fullscreens()); 189 EXPECT_EQ(1, observer_->num_not_fullscreens()); 190 191 // We also shouldn't report video in a window that's fully offscreen. 192 observer_->reset_stats(); 193 AdvanceTime(base::TimeDelta::FromSeconds(2)); 194 gfx::Rect offscreen_bounds( 195 gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0), 196 window_bounds.size()); 197 window->SetBounds(offscreen_bounds); 198 ASSERT_EQ(offscreen_bounds, window->bounds()); 199 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 200 detector_->OnWindowPaintScheduled(window.get(), update_region); 201 EXPECT_EQ(0, observer_->num_invocations()); 202} 203 204TEST_F(VideoDetectorTest, MultipleWindows) { 205 // Create two windows. 206 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 207 scoped_ptr<aura::Window> window1( 208 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 209 scoped_ptr<aura::Window> window2( 210 CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds)); 211 212 // Even if there's video playing in both, the observer should only receive a 213 // single notification. 214 gfx::Rect update_region( 215 gfx::Point(), 216 gfx::Size(VideoDetector::kMinUpdateWidth, 217 VideoDetector::kMinUpdateHeight)); 218 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 219 detector_->OnWindowPaintScheduled(window1.get(), update_region); 220 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 221 detector_->OnWindowPaintScheduled(window2.get(), update_region); 222 EXPECT_EQ(1, observer_->num_invocations()); 223 EXPECT_EQ(0, observer_->num_fullscreens()); 224 EXPECT_EQ(1, observer_->num_not_fullscreens()); 225} 226 227// Test that the observer receives repeated notifications. 228TEST_F(VideoDetectorTest, RepeatedNotifications) { 229 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 230 scoped_ptr<aura::Window> window( 231 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 232 233 gfx::Rect update_region( 234 gfx::Point(), 235 gfx::Size(VideoDetector::kMinUpdateWidth, 236 VideoDetector::kMinUpdateHeight)); 237 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 238 detector_->OnWindowPaintScheduled(window.get(), update_region); 239 EXPECT_EQ(1, observer_->num_invocations()); 240 EXPECT_EQ(0, observer_->num_fullscreens()); 241 EXPECT_EQ(1, observer_->num_not_fullscreens()); 242 // Let enough time pass that a second notification should be sent. 243 observer_->reset_stats(); 244 AdvanceTime(base::TimeDelta::FromSeconds( 245 static_cast<int64>(VideoDetector::kNotifyIntervalSec + 1))); 246 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 247 detector_->OnWindowPaintScheduled(window.get(), update_region); 248 EXPECT_EQ(1, observer_->num_invocations()); 249 EXPECT_EQ(0, observer_->num_fullscreens()); 250 EXPECT_EQ(1, observer_->num_not_fullscreens()); 251} 252 253// Test that the observer receives a true value when the window is fullscreen. 254TEST_F(VideoDetectorTest, FullscreenWindow) { 255 gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); 256 scoped_ptr<aura::Window> window( 257 CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); 258 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); 259 window->Focus(); 260 gfx::Rect update_region( 261 gfx::Point(), 262 gfx::Size(VideoDetector::kMinUpdateWidth, 263 VideoDetector::kMinUpdateHeight)); 264 for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) 265 detector_->OnWindowPaintScheduled(window.get(), update_region); 266 EXPECT_EQ(1, observer_->num_invocations()); 267 EXPECT_EQ(1, observer_->num_fullscreens()); 268 EXPECT_EQ(0, observer_->num_not_fullscreens()); 269} 270 271} // namespace test 272} // namespace ash 273