OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 <memory> | |
6 #include <vector> | |
7 | |
8 #include "base/command_line.h" | |
9 #include "base/logging.h" | |
10 #include "base/memory/ptr_util.h" | |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "services/ui/common/task_runner_test_base.h" | |
13 #include "services/ui/display/screen_manager_ozone.h" | |
14 #include "services/ui/display/viewport_metrics.h" | |
15 #include "testing/gmock/include/gmock/gmock.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 #include "ui/display/display.h" | |
18 #include "ui/display/display_switches.h" | |
19 #include "ui/display/fake_display_delegate.h" | |
20 #include "ui/display/fake_display_snapshot.h" | |
21 #include "ui/display/screen.h" | |
22 #include "ui/display/types/display_constants.h" | |
23 #include "ui/display/types/display_mode.h" | |
24 #include "ui/display/types/display_snapshot.h" | |
25 #include "ui/display/types/fake_display_controller.h" | |
26 #include "ui/events/devices/device_data_manager.h" | |
27 #include "ui/ozone/public/ozone_platform.h" | |
28 | |
29 namespace display { | |
30 | |
31 using testing::IsEmpty; | |
32 using testing::SizeIs; | |
33 | |
34 namespace { | |
35 | |
36 // Holds info about the display state we want to test. | |
37 struct DisplayState { | |
38 int64_t id; | |
39 ViewportMetrics metrics; | |
40 }; | |
41 | |
42 // Matchers that operate on DisplayState. | |
43 MATCHER_P(DisplayIdIs, display_id, "") { | |
44 *result_listener << "has id " << arg.id; | |
45 return arg.id == display_id; | |
46 } | |
47 | |
48 MATCHER_P(DisplayPixelSizeIs, size_string, "") { | |
49 *result_listener << "has size " << arg.metrics.pixel_size.ToString(); | |
50 return arg.metrics.pixel_size.ToString() == size_string; | |
51 } | |
52 | |
53 MATCHER_P(DisplayBoundsIs, bounds_string, "") { | |
54 *result_listener << "has size " << arg.metrics.bounds.ToString(); | |
55 return arg.metrics.bounds.ToString() == bounds_string; | |
56 } | |
57 | |
58 // Test delegate to track what functions calls the delegate receives. | |
59 class TestScreenManagerDelegate : public ScreenManagerDelegate { | |
60 public: | |
61 TestScreenManagerDelegate() {} | |
62 ~TestScreenManagerDelegate() override {} | |
63 | |
64 const std::vector<DisplayState>& added() const { return added_; } | |
65 const std::vector<DisplayState>& modified() const { return modified_; } | |
66 | |
67 // Returns a string containing the function calls that ScreenManagerDelegate | |
68 // has received in the order they occured. Each function call will be in the | |
69 // form "<action>(<id>)" and multiple function calls will be separated by ";". | |
70 // For example, if display 2 was added then display 1 was modified, changes() | |
71 // would return "Added(2);Modified(1)". | |
72 const std::string& changes() const { return changes_; } | |
73 | |
74 void Reset() { | |
75 added_.clear(); | |
76 modified_.clear(); | |
77 changes_.clear(); | |
78 } | |
79 | |
80 private: | |
81 void AddChange(const std::string& name, const std::string& value) { | |
82 if (!changes_.empty()) | |
83 changes_ += ";"; | |
84 changes_ += name + "(" + value + ")"; | |
85 } | |
86 | |
87 void OnDisplayAdded(int64_t id, const ViewportMetrics& metrics) override { | |
88 added_.push_back({id, metrics}); | |
89 AddChange("Added", base::Int64ToString(id)); | |
90 } | |
91 | |
92 void OnDisplayRemoved(int64_t id) override { | |
93 AddChange("Removed", base::Int64ToString(id)); | |
94 } | |
95 | |
96 void OnDisplayModified(int64_t id, const ViewportMetrics& metrics) override { | |
97 modified_.push_back({id, metrics}); | |
98 AddChange("Modified", base::Int64ToString(id)); | |
99 } | |
100 | |
101 void OnPrimaryDisplayChanged(int64_t primary_display_id) override { | |
102 AddChange("Primary", base::Int64ToString(primary_display_id)); | |
103 } | |
104 | |
105 std::vector<DisplayState> added_; | |
106 std::vector<DisplayState> modified_; | |
107 std::string changes_; | |
108 | |
109 DISALLOW_COPY_AND_ASSIGN(TestScreenManagerDelegate); | |
110 }; | |
111 | |
112 } // namespace | |
113 | |
114 // Test fixture with helpers to act like DisplayConfigurator and send | |
115 // OnDisplayModeChanged() to ScreenManagerOzone. | |
116 class ScreenManagerOzoneTest : public ui::TaskRunnerTestBase { | |
117 public: | |
118 ScreenManagerOzoneTest() {} | |
119 ~ScreenManagerOzoneTest() override {} | |
120 | |
121 ScreenManagerOzone* screen_manager() { return screen_manager_.get(); } | |
122 TestScreenManagerDelegate* delegate() { return &delegate_; } | |
123 | |
124 // Adds a display snapshot with specified ID and default size. | |
125 void AddDisplay(int64_t id) { | |
126 return AddDisplay(FakeDisplaySnapshot::Builder() | |
127 .SetId(id) | |
128 .SetNativeMode(gfx::Size(1024, 768)) | |
129 .Build()); | |
130 } | |
131 | |
132 void AddDisplay(std::unique_ptr<DisplaySnapshot> snapshot) { | |
133 EXPECT_TRUE(fake_display_controller_->AddDisplay(std::move(snapshot))); | |
134 RunAllTasks(); | |
135 } | |
136 | |
137 // Removes display snapshot with specified ID. | |
138 void RemoveDisplay(int64_t id) { | |
139 EXPECT_TRUE(fake_display_controller_->RemoveDisplay(id)); | |
140 RunAllTasks(); | |
141 } | |
142 | |
143 static void SetUpTestCase() { ui::DeviceDataManager::CreateInstance(); } | |
144 | |
145 static void TearDownTestCase() { ui::DeviceDataManager::DeleteInstance(); } | |
146 | |
147 private: | |
148 // testing::Test: | |
149 void SetUp() override { | |
150 TaskRunnerTestBase::SetUp(); | |
151 | |
152 base::CommandLine::ForCurrentProcess()->AppendSwitchNative( | |
153 switches::kScreenConfig, "none"); | |
154 | |
155 screen_manager_ = base::MakeUnique<ScreenManagerOzone>(); | |
156 | |
157 // Create NDD for FakeDisplayController. | |
158 std::unique_ptr<NativeDisplayDelegate> ndd = | |
159 base::MakeUnique<FakeDisplayDelegate>(); | |
160 fake_display_controller_ = ndd->GetFakeDisplayController(); | |
161 | |
162 // Add NDD to ScreenManager so one isn't loaded from Ozone. | |
163 screen_manager_->native_display_delegate_ = std::move(ndd); | |
164 | |
165 AddDisplay(FakeDisplaySnapshot::Builder() | |
166 .SetId(1) | |
167 .SetNativeMode(gfx::Size(1024, 768)) | |
168 .SetType(DISPLAY_CONNECTION_TYPE_INTERNAL) | |
169 .Build()); | |
170 | |
171 screen_manager_->Init(&delegate_); | |
172 RunAllTasks(); | |
173 | |
174 // Double check the expected display exists and clear counters. | |
175 ASSERT_THAT(delegate()->added(), SizeIs(1)); | |
176 ASSERT_THAT(delegate_.added()[0], DisplayIdIs(1)); | |
177 ASSERT_THAT(delegate_.added()[0], DisplayBoundsIs("0,0 1024x768")); | |
178 ASSERT_THAT(delegate_.added()[0], DisplayPixelSizeIs("1024x768")); | |
179 ASSERT_EQ("Added(1);Primary(1)", delegate()->changes()); | |
180 delegate_.Reset(); | |
181 } | |
182 | |
183 void TearDown() override { | |
184 delegate_.Reset(); | |
185 screen_manager_.reset(); | |
186 } | |
187 | |
188 FakeDisplayController* fake_display_controller_ = nullptr; | |
189 TestScreenManagerDelegate delegate_; | |
190 std::unique_ptr<ScreenManagerOzone> screen_manager_; | |
191 }; | |
192 | |
193 TEST_F(ScreenManagerOzoneTest, AddDisplay) { | |
194 AddDisplay(FakeDisplaySnapshot::Builder() | |
195 .SetId(2) | |
196 .SetNativeMode(gfx::Size(1600, 900)) | |
197 .Build()); | |
198 | |
199 // Check that display 2 was added with expected bounds and pixel_size. | |
200 EXPECT_EQ("Added(2)", delegate()->changes()); | |
201 EXPECT_THAT(delegate()->added()[0], DisplayPixelSizeIs("1600x900")); | |
202 EXPECT_THAT(delegate()->added()[0], DisplayBoundsIs("1024,0 1600x900")); | |
203 } | |
204 | |
205 TEST_F(ScreenManagerOzoneTest, RemoveDisplay) { | |
206 AddDisplay(2); | |
207 delegate()->Reset(); | |
208 | |
209 RemoveDisplay(2); | |
210 | |
211 // Check that display 2 was removed. | |
212 EXPECT_EQ("Removed(2)", delegate()->changes()); | |
213 } | |
214 | |
215 TEST_F(ScreenManagerOzoneTest, DISABLED_RemovePrimaryDisplay) { | |
216 AddDisplay(2); | |
217 delegate()->Reset(); | |
218 | |
219 RemoveDisplay(1); | |
220 | |
221 // Check that display 1 was removed and display 2 becomes the primary display | |
222 // and has it's origin change. | |
223 EXPECT_EQ("Removed(1);Modified(2);Primary(2)", delegate()->changes()); | |
224 ASSERT_THAT(delegate()->modified(), SizeIs(1)); | |
225 EXPECT_THAT(delegate()->modified()[0], DisplayIdIs(2)); | |
226 EXPECT_THAT(delegate()->modified()[0], DisplayBoundsIs("0,0 1024x768")); | |
227 } | |
228 | |
229 TEST_F(ScreenManagerOzoneTest, AddRemoveMultipleDisplay) { | |
230 AddDisplay(2); | |
231 AddDisplay(3); | |
232 EXPECT_EQ("Added(2);Added(3)", delegate()->changes()); | |
233 EXPECT_THAT(delegate()->added()[0], DisplayBoundsIs("1024,0 1024x768")); | |
234 EXPECT_THAT(delegate()->added()[1], DisplayBoundsIs("2048,0 1024x768")); | |
235 delegate()->Reset(); | |
236 | |
237 // Check that display 2 was removed and display 3 origin changed. | |
238 RemoveDisplay(2); | |
239 EXPECT_EQ("Removed(2);Modified(3)", delegate()->changes()); | |
240 EXPECT_THAT(delegate()->modified()[0], DisplayBoundsIs("1024,0 1024x768")); | |
241 delegate()->Reset(); | |
242 | |
243 // Check that display 3 was removed. | |
244 RemoveDisplay(3); | |
245 EXPECT_EQ("Removed(3)", delegate()->changes()); | |
246 } | |
247 | |
248 TEST_F(ScreenManagerOzoneTest, AddDisplay4k) { | |
249 AddDisplay(FakeDisplaySnapshot::Builder() | |
250 .SetId(2) | |
251 .SetNativeMode(gfx::Size(4096, 2160)) | |
252 .SetType(DISPLAY_CONNECTION_TYPE_DVI) | |
253 .Build()); | |
254 | |
255 // Check that display 2 has a device scale factor of 2 since it's a 4k | |
256 // display. | |
257 EXPECT_EQ("Added(2)", delegate()->changes()); | |
258 EXPECT_THAT(delegate()->added()[0], DisplayBoundsIs("1024,0 2048x1080")); | |
259 EXPECT_THAT(delegate()->added()[0], DisplayPixelSizeIs("4096x2160")); | |
260 } | |
261 | |
262 TEST_F(ScreenManagerOzoneTest, SwapPrimaryDisplay) { | |
263 AddDisplay(2); | |
264 delegate()->Reset(); | |
265 | |
266 EXPECT_EQ(1, Screen::GetScreen()->GetPrimaryDisplay().id()); | |
267 | |
268 // Swapping displays will modify the bounds of both displays and change the | |
269 // primary. | |
270 screen_manager()->SwapPrimaryDisplay(); | |
271 EXPECT_EQ("Modified(1);Modified(2);Primary(2)", delegate()->changes()); | |
272 EXPECT_THAT(delegate()->modified()[0], DisplayBoundsIs("-1024,0 1024x768")); | |
273 EXPECT_THAT(delegate()->modified()[1], DisplayBoundsIs("0,0 1024x768")); | |
274 EXPECT_EQ(2, Screen::GetScreen()->GetPrimaryDisplay().id()); | |
275 delegate()->Reset(); | |
276 | |
277 // Swapping again should be similar and end up back with display 1 as primary. | |
278 screen_manager()->SwapPrimaryDisplay(); | |
279 EXPECT_EQ("Modified(1);Modified(2);Primary(1)", delegate()->changes()); | |
280 EXPECT_THAT(delegate()->modified()[0], DisplayBoundsIs("0,0 1024x768")); | |
281 EXPECT_THAT(delegate()->modified()[1], DisplayBoundsIs("1024,0 1024x768")); | |
282 EXPECT_EQ(1, Screen::GetScreen()->GetPrimaryDisplay().id()); | |
283 } | |
284 | |
285 } // namespace display | |
OLD | NEW |