Chromium Code Reviews| Index: content/browser/media/capture/cursor_renderer_aura_unittest.cc |
| diff --git a/content/browser/media/capture/cursor_renderer_aura_unittest.cc b/content/browser/media/capture/cursor_renderer_aura_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2d2d6ed1533a3d847c68004d7d35bb52425f613c |
| --- /dev/null |
| +++ b/content/browser/media/capture/cursor_renderer_aura_unittest.cc |
| @@ -0,0 +1,196 @@ |
| +// Copyright (c) 2015 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 "content/browser/media/capture/cursor_renderer_aura.h" |
| + |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/test/simple_test_tick_clock.h" |
| +#include "base/time/time.h" |
| +#include "media/base/video_frame.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "ui/aura/env.h" |
| +#include "ui/aura/test/aura_test_base.h" |
| +#include "ui/aura/test/test_windows.h" |
| +#include "ui/aura/window.h" |
| +#include "ui/base/resource/resource_bundle.h" |
| +#include "ui/events/event.h" |
| +#include "ui/events/event_utils.h" |
| +#include "ui/wm/core/default_activation_client.h" |
| +#include "ui/wm/core/window_util.h" |
| + |
| +namespace content { |
| + |
| +using aura::test::AuraTestBase; |
| + |
| +class CursorRendererAuraTest : public AuraTestBase { |
| + public: |
| + CursorRendererAuraTest() {} |
| + ~CursorRendererAuraTest() override {} |
| + |
| + void SetUp() override { |
| + AuraTestBase::SetUp(); |
| + // This is needed to avoid duplicate initialization across tests that leads |
| + // to a failure. |
| + if (!ui::ResourceBundle::HasSharedInstance()) { |
| + // Initialize the shared global resource bundle that has bitmap |
| + // resources needed by CursorRenderer |
| + ui::ResourceBundle::InitSharedInstanceWithLocale( |
| + "en-US", NULL, ui::ResourceBundle::LOAD_COMMON_RESOURCES); |
|
miu
2015/10/29 01:44:49
nit: nullptr instead of NULL
Irfan
2015/10/29 15:34:19
Done.
|
| + } |
| + |
| + window_.reset(aura::test::CreateTestWindowWithBounds( |
| + gfx::Rect(0, 0, 800, 600), root_window())); |
| + cursor_renderer_.reset(new CursorRendererAura(window_.get())); |
| + new wm::DefaultActivationClient(root_window()); |
| + } |
| + |
| + void TearDown() override { |
| + cursor_renderer_.reset(); |
| + window_.reset(); |
| + AuraTestBase::TearDown(); |
| + } |
| + |
| + void SetTickClock(base::SimpleTestTickClock* clock) { |
| + cursor_renderer_->tick_clock_ = clock; |
| + } |
| + |
| + base::TimeDelta Now() { |
| + return cursor_renderer_->tick_clock_->NowTicks() - base::TimeTicks(); |
| + } |
| + |
| + bool CursorDisplayed() { return cursor_renderer_->cursor_displayed_; } |
| + |
| + void RenderCursorOnVideoFrame( |
| + const scoped_refptr<media::VideoFrame>& target) { |
| + cursor_renderer_->RenderOnVideoFrame(target); |
| + } |
| + |
| + void SnapshotCursorState(gfx::Rect region_in_frame) { |
| + cursor_renderer_->SnapshotCursorState(region_in_frame); |
| + } |
| + |
| + void MoveMouseCursorWithinWindow() { |
| + gfx::Point point1(20, 20); |
| + ui::MouseEvent event1(ui::ET_MOUSE_MOVED, point1, point1, Now(), 0, 0); |
| + cursor_renderer_->OnMouseEvent(&event1); |
| + gfx::Point point2(60, 60); |
| + ui::MouseEvent event2(ui::ET_MOUSE_MOVED, point2, point2, Now(), 0, 0); |
| + cursor_renderer_->OnMouseEvent(&event2); |
| + aura::Env::GetInstance()->set_last_mouse_location(point2); |
| + } |
| + |
| + void MoveMouseCursorWithinWindow(gfx::Point point) { |
| + ui::MouseEvent event(ui::ET_MOUSE_MOVED, point, point, Now(), 0, 0); |
| + cursor_renderer_->OnMouseEvent(&event); |
| + aura::Env::GetInstance()->set_last_mouse_location(point); |
| + } |
| + |
| + void MoveMouseCursorOutsideWindow() { |
| + gfx::Point point(1000, 1000); |
| + ui::MouseEvent event1(ui::ET_MOUSE_MOVED, point, point, Now(), 0, 0); |
| + cursor_renderer_->OnMouseEvent(&event1); |
| + aura::Env::GetInstance()->set_last_mouse_location(point); |
|
sadrul
2015/10/29 06:22:41
Most tests usually use EventGenerator for sending
Irfan
2015/10/29 15:34:19
This allows me to stay in control of clock. Keepin
|
| + } |
| + |
| + // A very simple test of whether there are any non-zero pixels |
| + // in the region |rect| within |frame|. |
| + bool NonZeroPixelsInRegion(scoped_refptr<media::VideoFrame> frame, |
| + gfx::Rect rect) { |
| + bool y_found = false, u_found = false, v_found = false; |
| + for (int y = rect.y(); y < rect.bottom(); ++y) { |
| + uint8* yplane = frame->data(media::VideoFrame::kYPlane) + |
| + y * frame->row_bytes(media::VideoFrame::kYPlane); |
| + uint8* uplane = frame->data(media::VideoFrame::kUPlane) + |
| + (y / 2) * frame->row_bytes(media::VideoFrame::kUPlane); |
| + uint8* vplane = frame->data(media::VideoFrame::kVPlane) + |
| + (y / 2) * frame->row_bytes(media::VideoFrame::kVPlane); |
| + for (int x = rect.x(); x < rect.right(); ++x) { |
| + if (yplane[x] != 0) |
| + y_found = true; |
| + if (uplane[x / 2]) |
| + u_found = true; |
| + if (vplane[x / 2]) |
| + v_found = true; |
| + } |
| + } |
| + return (y_found && u_found && v_found); |
| + } |
| + |
| + protected: |
| + scoped_ptr<aura::Window> window_; |
| + scoped_ptr<CursorRendererAura> cursor_renderer_; |
| +}; |
| + |
| +TEST_F(CursorRendererAuraTest, CursorDuringMouseMovement) { |
| + // Keep window activated. |
| + wm::ActivateWindow(window_.get()); |
| + |
| + EXPECT_FALSE(CursorDisplayed()); |
| + |
| + base::SimpleTestTickClock clock; |
| + SetTickClock(&clock); |
| + |
| + // Cursor displayed after mouse movement. |
| + MoveMouseCursorWithinWindow(); |
| + EXPECT_TRUE(CursorDisplayed()); |
| + |
| + // Cursor not be displayed after idle period. |
| + clock.Advance(base::TimeDelta::FromSeconds(5)); |
| + SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| + EXPECT_FALSE(CursorDisplayed()); |
| + |
| + // Cursor displayed with mouse movement following idle period. |
| + MoveMouseCursorWithinWindow(); |
| + SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| + EXPECT_TRUE(CursorDisplayed()); |
| + |
| + // Cursor not displayed if mouse outside the window |
| + MoveMouseCursorOutsideWindow(); |
| + SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| + EXPECT_FALSE(CursorDisplayed()); |
| +} |
| + |
| +TEST_F(CursorRendererAuraTest, CursorOnActiveWindow) { |
| + EXPECT_FALSE(CursorDisplayed()); |
| + |
| + // Cursor displayed after mouse movement. |
| + MoveMouseCursorWithinWindow(); |
| + EXPECT_TRUE(CursorDisplayed()); |
| + |
| + // Cursor not be displayed if a second window is activated. |
| + scoped_ptr<aura::Window> window2(aura::test::CreateTestWindowWithBounds( |
| + gfx::Rect(0, 0, 800, 600), root_window())); |
| + wm::ActivateWindow(window2.get()); |
| + SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| + EXPECT_FALSE(CursorDisplayed()); |
| + |
| + // Cursor displayed if window activated again. |
| + MoveMouseCursorWithinWindow(); |
| + wm::ActivateWindow(window_.get()); |
| + SnapshotCursorState(gfx::Rect(10, 10, 200, 200)); |
| + EXPECT_TRUE(CursorDisplayed()); |
| +} |
| + |
| +TEST_F(CursorRendererAuraTest, CursorRenderedOnFrame) { |
| + // Keep window activated. |
| + wm::ActivateWindow(window_.get()); |
| + |
| + EXPECT_FALSE(CursorDisplayed()); |
| + |
| + gfx::Size size(800, 600); |
| + scoped_refptr<media::VideoFrame> frame = |
| + media::VideoFrame::CreateZeroInitializedFrame(media::PIXEL_FORMAT_YV12, |
| + size, gfx::Rect(size), size, |
| + base::TimeDelta()); |
| + |
| + MoveMouseCursorWithinWindow(gfx::Point(60, 60)); |
| + SnapshotCursorState(gfx::Rect(size)); |
| + EXPECT_TRUE(CursorDisplayed()); |
| + |
| + EXPECT_FALSE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70))); |
| + RenderCursorOnVideoFrame(frame); |
| + EXPECT_TRUE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70))); |
| +} |
| + |
| +} // namespace content |