Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(578)

Side by Side Diff: content/browser/media/capture/cursor_renderer_mac_unittest.mm

Issue 2682743006: Add unittests for CursorRendererMac (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 "content/browser/media/capture/cursor_renderer_mac.h"
6
7 #include <Cocoa/Cocoa.h>
8
9 #include "base/mac/scoped_nsobject.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "media/base/video_frame.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/gfx/test/ui_cocoa_test_helper.h"
15
16 namespace content {
17
18 const int kTestViewWidth = 800;
19 const int kTestViewHeight = 600;
20
21 class CursorRendererMacTest : public ui::CocoaTest {
22 public:
23 CursorRendererMacTest() {}
24 ~CursorRendererMacTest() override{};
25
26 void SetUp() override {
27 ui::CocoaTest::SetUp();
28 base::scoped_nsobject<NSView> view([[NSView alloc]
29 initWithFrame:NSMakeRect(0, 0, kTestViewWidth, kTestViewHeight)]);
30 view_ = view.get();
31 [[test_window() contentView] addSubview:view_];
32
33 cursor_renderer_.reset(new CursorRendererMac(view_));
34 }
35
36 void TearDown() override {
37 cursor_renderer_.reset();
38 ui::CocoaTest::TearDown();
39 }
40
41 void SetTickClock(base::SimpleTestTickClock* clock) {
42 cursor_renderer_->tick_clock_ = clock;
43 }
44
45 bool CursorDisplayed() { return cursor_renderer_->cursor_displayed_; }
46
47 void RenderCursorOnVideoFrame(media::VideoFrame* target) {
48 cursor_renderer_->RenderOnVideoFrame(target);
49 }
50
51 void SnapshotCursorState(gfx::Rect region_in_frame) {
52 cursor_renderer_->SnapshotCursorState(region_in_frame);
53 }
54
55 // Here the |point| is in Aura coordinates (the origin (0, 0) is at top-left
56 // of the view). To move the cursor to that point by Quartz Dislay service,
miu 2017/02/09 21:54:07 s/Dislay/Display/
braveyao 2017/02/09 23:15:36 Done.
57 // we need to convert it into Cocoa coordinates(the origin is at bottom-left
miu 2017/02/09 21:54:07 nit: space before parenthesis.
miu 2017/02/09 21:54:07 style nit: Don't use "we" in comments. Use 3rd-per
braveyao 2017/02/09 23:15:36 Done.
braveyao 2017/02/09 23:15:36 Done.
58 // of the main screen) first, and then convert it info Quartz coordinates
59 // (the origin is at top-left of the main display).
60 void MoveMouseCursorWithinWindow(gfx::Point point) {
miu 2017/02/09 21:54:07 Instead of this method, there's already a utility
braveyao 2017/02/09 23:15:36 Done. And we still need to convert it to screen co
61 const int display_height = CGDisplayPixelsHigh(CGMainDisplayID());
62 const int converted_y = display_height - kTestViewHeight + point.y();
63 CGWarpMouseCursorPosition(CGPointMake(point.x(), converted_y));
64 cursor_renderer_->OnMouseEvent();
65 }
66
67 void MoveMouseCursorWithinWindow() {
68 const int display_height = CGDisplayPixelsHigh(CGMainDisplayID());
miu 2017/02/09 21:54:07 ditto here: Use existing utility function.
braveyao 2017/02/09 23:15:36 Done.
69 int converted_y = display_height - kTestViewHeight + 50;
70 CGWarpMouseCursorPosition(CGPointMake(50, converted_y));
71 cursor_renderer_->OnMouseEvent();
72
73 converted_y = display_height - kTestViewHeight + 100;
74 CGWarpMouseCursorPosition(CGPointMake(100, converted_y));
75 cursor_renderer_->OnMouseEvent();
76 }
77
78 void MoveMouseCursorOutsideWindow() {
79 CGWarpMouseCursorPosition(CGPointMake(1000, 200));
80 cursor_renderer_->OnMouseEvent();
81 }
82
83 // A very simple test of whether there are any non-zero pixels
84 // in the region |rect| within |frame|.
85 bool NonZeroPixelsInRegion(scoped_refptr<media::VideoFrame> frame,
86 gfx::Rect rect) {
87 bool y_found = false, u_found = false, v_found = false;
88 for (int y = rect.y(); y < rect.bottom(); ++y) {
89 uint8_t* yplane = frame->data(media::VideoFrame::kYPlane) +
90 y * frame->row_bytes(media::VideoFrame::kYPlane);
91 uint8_t* uplane = frame->data(media::VideoFrame::kUPlane) +
92 (y / 2) * frame->row_bytes(media::VideoFrame::kUPlane);
93 uint8_t* vplane = frame->data(media::VideoFrame::kVPlane) +
94 (y / 2) * frame->row_bytes(media::VideoFrame::kVPlane);
95 for (int x = rect.x(); x < rect.right(); ++x) {
96 if (yplane[x] != 0)
97 y_found = true;
98 if (uplane[x / 2])
99 u_found = true;
100 if (vplane[x / 2])
101 v_found = true;
102 }
103 }
104 return (y_found && u_found && v_found);
105 }
106
107 protected:
108 NSView* view_;
109 std::unique_ptr<CursorRendererMac> cursor_renderer_;
110 };
111
112 TEST_F(CursorRendererMacTest, CursorDuringMouseMovement) {
113 // Keep window activated.
114 [test_window() setPretendIsKeyWindow:YES];
115
116 EXPECT_FALSE(CursorDisplayed());
117
118 base::SimpleTestTickClock clock;
119 SetTickClock(&clock);
120
121 // Cursor displayed after mouse movement.
122 MoveMouseCursorWithinWindow();
123 EXPECT_TRUE(CursorDisplayed());
124
125 // Cursor not be displayed after idle period.
126 clock.SetNowTicks(base::TimeTicks::Now());
127 clock.Advance(base::TimeDelta::FromSeconds(5));
128 SnapshotCursorState(gfx::Rect(10, 10, 200, 200));
129 EXPECT_FALSE(CursorDisplayed());
130 clock.SetNowTicks(base::TimeTicks::Now());
131
132 // Cursor displayed with mouse movement following idle period.
133 MoveMouseCursorWithinWindow();
134 SnapshotCursorState(gfx::Rect(10, 10, 200, 200));
135 EXPECT_TRUE(CursorDisplayed());
136
137 // Cursor not displayed if mouse outside the window
138 MoveMouseCursorOutsideWindow();
139 SnapshotCursorState(gfx::Rect(10, 10, 200, 200));
140 EXPECT_FALSE(CursorDisplayed());
141 }
142
143 TEST_F(CursorRendererMacTest, CursorOnActiveWindow) {
144 EXPECT_FALSE(CursorDisplayed());
145
146 // Cursor displayed after mouse movement.
147 [test_window() setPretendIsKeyWindow:YES];
148 MoveMouseCursorWithinWindow();
149 EXPECT_TRUE(CursorDisplayed());
150
151 // Cursor not be displayed if window is not activated.
152 [test_window() setPretendIsKeyWindow:NO];
153 SnapshotCursorState(gfx::Rect(10, 10, 200, 200));
154 EXPECT_FALSE(CursorDisplayed());
155
156 // Cursor is displayed again if window is activated again.
157 [test_window() setPretendIsKeyWindow:YES];
158 MoveMouseCursorWithinWindow();
159 SnapshotCursorState(gfx::Rect(10, 10, 200, 200));
160 EXPECT_TRUE(CursorDisplayed());
161 }
162
163 TEST_F(CursorRendererMacTest, CursorRenderedOnFrame) {
164 // Keep window activated.
165 [test_window() setPretendIsKeyWindow:YES];
166
167 EXPECT_FALSE(CursorDisplayed());
168
169 gfx::Size size(kTestViewWidth, kTestViewHeight);
170 scoped_refptr<media::VideoFrame> frame =
171 media::VideoFrame::CreateZeroInitializedFrame(media::PIXEL_FORMAT_YV12,
172 size, gfx::Rect(size), size,
173 base::TimeDelta());
174
175 MoveMouseCursorWithinWindow(gfx::Point(60, 60));
176 SnapshotCursorState(gfx::Rect(size));
177 EXPECT_TRUE(CursorDisplayed());
178
179 EXPECT_FALSE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70)));
180 RenderCursorOnVideoFrame(frame.get());
181 EXPECT_TRUE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70)));
182 }
183
184 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698