Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / remoting / host / resizing_host_observer_unittest.cc
blobf25465afbc2bf879a4ea8d442b66a33a1989194e
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.
5 #include <list>
7 #include "base/compiler_specific.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "remoting/host/desktop_resizer.h"
13 #include "remoting/host/resizing_host_observer.h"
14 #include "remoting/host/screen_resolution.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
18 namespace remoting {
20 std::ostream& operator<<(std::ostream& os, const ScreenResolution& resolution) {
21 return os << resolution.dimensions().width() << "x"
22 << resolution.dimensions().height() << " @ "
23 << resolution.dpi().x() << "x" << resolution.dpi().y();
26 bool operator==(const ScreenResolution& a, const ScreenResolution& b) {
27 return a.Equals(b);
30 const int kDefaultDPI = 96;
32 ScreenResolution MakeResolution(int width, int height) {
33 return ScreenResolution(webrtc::DesktopSize(width, height),
34 webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
37 class FakeDesktopResizer : public DesktopResizer {
38 public:
39 FakeDesktopResizer(const ScreenResolution& initial_resolution,
40 bool exact_size_supported,
41 const ScreenResolution* supported_resolutions,
42 int num_supported_resolutions,
43 int* restore_resolution_call_count)
44 : initial_resolution_(initial_resolution),
45 current_resolution_(initial_resolution),
46 exact_size_supported_(exact_size_supported),
47 set_resolution_call_count_(0),
48 restore_resolution_call_count_(restore_resolution_call_count) {
49 for (int i = 0; i < num_supported_resolutions; ++i) {
50 supported_resolutions_.push_back(supported_resolutions[i]);
54 ~FakeDesktopResizer() override {
55 EXPECT_EQ(initial_resolution_, GetCurrentResolution());
58 int set_resolution_call_count() { return set_resolution_call_count_; }
60 // remoting::DesktopResizer interface
61 ScreenResolution GetCurrentResolution() override {
62 return current_resolution_;
64 std::list<ScreenResolution> GetSupportedResolutions(
65 const ScreenResolution& preferred) override {
66 std::list<ScreenResolution> result = supported_resolutions_;
67 if (exact_size_supported_) {
68 result.push_back(preferred);
70 return result;
72 void SetResolution(const ScreenResolution& resolution) override {
73 current_resolution_ = resolution;
74 ++set_resolution_call_count_;
76 void RestoreResolution(const ScreenResolution& resolution) override {
77 current_resolution_ = resolution;
78 if (restore_resolution_call_count_)
79 ++(*restore_resolution_call_count_);
82 private:
83 ScreenResolution initial_resolution_;
84 ScreenResolution current_resolution_;
85 bool exact_size_supported_;
86 std::list<ScreenResolution> supported_resolutions_;
88 int set_resolution_call_count_;
89 int* restore_resolution_call_count_;
92 class ResizingHostObserverTest : public testing::Test {
93 public:
94 ResizingHostObserverTest()
95 : desktop_resizer_(nullptr),
96 now_(base::Time::Now()) {
99 // This needs to be public because the derived test-case class needs to
100 // pass it to Bind, which fails if it's protected.
101 base::Time GetTime() {
102 return now_;
105 protected:
106 void SetDesktopResizer(scoped_ptr<FakeDesktopResizer> desktop_resizer) {
107 CHECK(!desktop_resizer_) << "Call SetDeskopResizer once per test";
108 desktop_resizer_ = desktop_resizer.get();
110 resizing_host_observer_.reset(
111 new ResizingHostObserver(desktop_resizer.Pass()));
112 resizing_host_observer_->SetNowFunctionForTesting(
113 base::Bind(&ResizingHostObserverTest::GetTimeAndIncrement,
114 base::Unretained(this)));
117 ScreenResolution GetBestResolution(const ScreenResolution& client_size) {
118 resizing_host_observer_->SetScreenResolution(client_size);
119 return desktop_resizer_->GetCurrentResolution();
122 void VerifySizes(const ScreenResolution* client_sizes,
123 const ScreenResolution* expected_sizes,
124 int number_of_sizes) {
125 for (int i = 0; i < number_of_sizes; ++i) {
126 ScreenResolution best_size = GetBestResolution(client_sizes[i]);
127 EXPECT_EQ(expected_sizes[i], best_size)
128 << "Input resolution = " << client_sizes[i];
132 base::Time GetTimeAndIncrement() {
133 base::Time result = now_;
134 now_ += base::TimeDelta::FromSeconds(1);
135 return result;
138 scoped_ptr<ResizingHostObserver> resizing_host_observer_;
139 FakeDesktopResizer* desktop_resizer_;
140 base::Time now_;
143 // Check that the resolution isn't restored if it wasn't changed by this class.
144 TEST_F(ResizingHostObserverTest, NoRestoreResolution) {
145 int restore_resolution_call_count = 0;
146 ScreenResolution initial = MakeResolution(640, 480);
147 scoped_ptr<FakeDesktopResizer> desktop_resizer(
148 new FakeDesktopResizer(initial, false, nullptr, 0,
149 &restore_resolution_call_count));
150 SetDesktopResizer(desktop_resizer.Pass());
151 VerifySizes(nullptr, nullptr, 0);
152 resizing_host_observer_.reset();
153 EXPECT_EQ(0, restore_resolution_call_count);
156 // Check that the host is not resized if GetSupportedSizes returns an empty
157 // list (even if GetCurrentSize is supported).
158 TEST_F(ResizingHostObserverTest, EmptyGetSupportedSizes) {
159 int restore_resolution_call_count = 0;
160 ScreenResolution initial = MakeResolution(640, 480);
161 scoped_ptr<FakeDesktopResizer> desktop_resizer(
162 new FakeDesktopResizer(initial, false, nullptr, 0,
163 &restore_resolution_call_count));
164 SetDesktopResizer(desktop_resizer.Pass());
166 ScreenResolution client_sizes[] = { MakeResolution(200, 100),
167 MakeResolution(100, 200) };
168 ScreenResolution expected_sizes[] = { initial, initial };
169 VerifySizes(client_sizes, expected_sizes, arraysize(client_sizes));
171 resizing_host_observer_.reset();
172 EXPECT_EQ(0, restore_resolution_call_count);
175 // Check that if the implementation supports exact size matching, it is used.
176 TEST_F(ResizingHostObserverTest, SelectExactSize) {
177 int restore_resolution_call_count = 0;
178 scoped_ptr<FakeDesktopResizer> desktop_resizer(
179 new FakeDesktopResizer(MakeResolution(640, 480), true, nullptr, 0,
180 &restore_resolution_call_count));
181 SetDesktopResizer(desktop_resizer.Pass());
183 ScreenResolution client_sizes[] = { MakeResolution(200, 100),
184 MakeResolution(100, 200),
185 MakeResolution(640, 480),
186 MakeResolution(480, 640),
187 MakeResolution(1280, 1024) };
188 VerifySizes(client_sizes, client_sizes, arraysize(client_sizes));
189 resizing_host_observer_.reset();
190 EXPECT_EQ(1, restore_resolution_call_count);
193 // Check that if the implementation supports a size that is no larger than
194 // the requested size, then the largest such size is used.
195 TEST_F(ResizingHostObserverTest, SelectBestSmallerSize) {
196 ScreenResolution supported_sizes[] = { MakeResolution(639, 479),
197 MakeResolution(640, 480) };
198 scoped_ptr<FakeDesktopResizer> desktop_resizer(
199 new FakeDesktopResizer(MakeResolution(640, 480), false,
200 supported_sizes, arraysize(supported_sizes),
201 nullptr));
202 SetDesktopResizer(desktop_resizer.Pass());
204 ScreenResolution client_sizes[] = { MakeResolution(639, 479),
205 MakeResolution(640, 480),
206 MakeResolution(641, 481),
207 MakeResolution(999, 999) };
208 ScreenResolution expected_sizes[] = { supported_sizes[0], supported_sizes[1],
209 supported_sizes[1], supported_sizes[1] };
210 VerifySizes(client_sizes, expected_sizes, arraysize(client_sizes));
213 // Check that if the implementation supports only sizes that are larger than
214 // the requested size, then the one that requires the least down-scaling.
215 TEST_F(ResizingHostObserverTest, SelectBestScaleFactor) {
216 ScreenResolution supported_sizes[] = { MakeResolution(100, 100),
217 MakeResolution(200, 100) };
218 scoped_ptr<FakeDesktopResizer> desktop_resizer(
219 new FakeDesktopResizer(MakeResolution(200, 100), false,
220 supported_sizes, arraysize(supported_sizes),
221 nullptr));
222 SetDesktopResizer(desktop_resizer.Pass());
224 ScreenResolution client_sizes[] = { MakeResolution(1, 1),
225 MakeResolution(99, 99),
226 MakeResolution(199, 99) };
227 ScreenResolution expected_sizes[] = { supported_sizes[0], supported_sizes[0],
228 supported_sizes[1] };
229 VerifySizes(client_sizes, expected_sizes, arraysize(client_sizes));
232 // Check that if the implementation supports two sizes that have the same
233 // resultant scale factor, then the widest one is selected.
234 TEST_F(ResizingHostObserverTest, SelectWidest) {
235 ScreenResolution supported_sizes[] = { MakeResolution(640, 480),
236 MakeResolution(480, 640) };
237 scoped_ptr<FakeDesktopResizer> desktop_resizer(
238 new FakeDesktopResizer(MakeResolution(480, 640), false,
239 supported_sizes, arraysize(supported_sizes),
240 nullptr));
241 SetDesktopResizer(desktop_resizer.Pass());
243 ScreenResolution client_sizes[] = { MakeResolution(100, 100),
244 MakeResolution(480, 480),
245 MakeResolution(500, 500),
246 MakeResolution(640, 640),
247 MakeResolution(1000, 1000) };
248 ScreenResolution expected_sizes[] = { supported_sizes[0], supported_sizes[0],
249 supported_sizes[0], supported_sizes[0],
250 supported_sizes[0] };
251 VerifySizes(client_sizes, expected_sizes, arraysize(client_sizes));
254 // Check that if the best match for the client size doesn't change, then we
255 // don't call SetSize.
256 TEST_F(ResizingHostObserverTest, NoSetSizeForSameSize) {
257 ScreenResolution supported_sizes[] = { MakeResolution(640, 480),
258 MakeResolution(480, 640) };
259 SetDesktopResizer(make_scoped_ptr(new FakeDesktopResizer(
260 MakeResolution(480, 640), false,
261 supported_sizes, arraysize(supported_sizes), nullptr)));
263 ScreenResolution client_sizes[] = { MakeResolution(640, 640),
264 MakeResolution(1024, 768),
265 MakeResolution(640, 480) };
266 ScreenResolution expected_sizes[] = { MakeResolution(640, 480),
267 MakeResolution(640, 480),
268 MakeResolution(640, 480) };
269 VerifySizes(client_sizes, expected_sizes, arraysize(client_sizes));
270 EXPECT_EQ(desktop_resizer_->set_resolution_call_count(), 1);
273 // Check that desktop resizes are rate-limited, and that if multiple resize
274 // requests are received in the time-out period, the most recent is respected.
275 TEST_F(ResizingHostObserverTest, RateLimited) {
276 SetDesktopResizer(make_scoped_ptr(new FakeDesktopResizer(
277 MakeResolution(640, 480), true, nullptr, 0, nullptr)));
278 resizing_host_observer_->SetNowFunctionForTesting(
279 base::Bind(&ResizingHostObserverTest::GetTime, base::Unretained(this)));
281 base::MessageLoop message_loop;
282 base::RunLoop run_loop;
284 EXPECT_EQ(GetBestResolution(MakeResolution(100, 100)),
285 MakeResolution(100, 100));
286 now_ += base::TimeDelta::FromMilliseconds(900);
287 EXPECT_EQ(GetBestResolution(MakeResolution(200, 200)),
288 MakeResolution(100, 100));
289 now_ += base::TimeDelta::FromMilliseconds(99);
290 EXPECT_EQ(GetBestResolution(MakeResolution(300, 300)),
291 MakeResolution(100, 100));
292 now_ += base::TimeDelta::FromMilliseconds(1);
294 // Due to the kMinimumResizeIntervalMs constant in resizing_host_observer.cc,
295 // We need to wait a total of 1000ms for the final resize to be processed.
296 // Since it was queued 900 + 99 ms after the first, we need to wait an
297 // additional 1ms. However, since RunLoop is not guaranteed to process tasks
298 // with the same due time in FIFO order, wait an additional 1ms for safety.
299 message_loop.PostDelayedTask(
300 FROM_HERE,
301 run_loop.QuitClosure(),
302 base::TimeDelta::FromMilliseconds(2));
303 run_loop.Run();
305 // If the QuitClosure fired before the final resize, it's a test failure.
306 EXPECT_EQ(desktop_resizer_->GetCurrentResolution(), MakeResolution(300, 300));
309 } // namespace remoting