Upstream version 10.39.233.0
[platform/framework/web/crosswalk.git] / src / remoting / host / resizing_host_observer_unittest.cc
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 <list>
6
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"
17
18 namespace remoting {
19
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();
24 }
25
26 bool operator==(const ScreenResolution& a, const ScreenResolution& b) {
27   return a.Equals(b);
28 }
29
30 const int kDefaultDPI = 96;
31
32 ScreenResolution MakeResolution(int width, int height) {
33   return ScreenResolution(webrtc::DesktopSize(width, height),
34                           webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
35 }
36
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]);
51     }
52   }
53
54   virtual ~FakeDesktopResizer() {
55     EXPECT_EQ(initial_resolution_, GetCurrentResolution());
56   }
57
58   int set_resolution_call_count() { return set_resolution_call_count_; }
59
60   // remoting::DesktopResizer interface
61   virtual ScreenResolution GetCurrentResolution() OVERRIDE {
62     return current_resolution_;
63   }
64   virtual 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);
69     }
70     return result;
71   }
72   virtual void SetResolution(const ScreenResolution& resolution) OVERRIDE {
73     current_resolution_ = resolution;
74     ++set_resolution_call_count_;
75   }
76   virtual void RestoreResolution(const ScreenResolution& resolution) OVERRIDE {
77     current_resolution_ = resolution;
78     if (restore_resolution_call_count_)
79       ++(*restore_resolution_call_count_);
80   }
81
82  private:
83   ScreenResolution initial_resolution_;
84   ScreenResolution current_resolution_;
85   bool exact_size_supported_;
86   std::list<ScreenResolution> supported_resolutions_;
87
88   int set_resolution_call_count_;
89   int* restore_resolution_call_count_;
90 };
91
92 class ResizingHostObserverTest : public testing::Test {
93  public:
94   ResizingHostObserverTest()
95       : desktop_resizer_(NULL),
96         now_(base::Time::Now()) {
97   }
98
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_;
103   }
104
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();
109
110     resizing_host_observer_.reset(
111         new ResizingHostObserver(desktop_resizer.PassAs<DesktopResizer>()));
112     resizing_host_observer_->SetNowFunctionForTesting(
113         base::Bind(&ResizingHostObserverTest::GetTimeAndIncrement,
114                    base::Unretained(this)));
115   }
116
117   ScreenResolution GetBestResolution(const ScreenResolution& client_size) {
118     resizing_host_observer_->SetScreenResolution(client_size);
119     return desktop_resizer_->GetCurrentResolution();
120   }
121
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];
129     }
130   }
131
132   base::Time GetTimeAndIncrement() {
133     base::Time result = now_;
134     now_ += base::TimeDelta::FromSeconds(1);
135     return result;
136   }
137
138   scoped_ptr<ResizingHostObserver> resizing_host_observer_;
139   FakeDesktopResizer* desktop_resizer_;
140   base::Time now_;
141 };
142
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, NULL, 0,
149                              &restore_resolution_call_count));
150   SetDesktopResizer(desktop_resizer.Pass());
151   VerifySizes(NULL, NULL, 0);
152   resizing_host_observer_.reset();
153   EXPECT_EQ(0, restore_resolution_call_count);
154 }
155
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, NULL, 0,
163                              &restore_resolution_call_count));
164   SetDesktopResizer(desktop_resizer.Pass());
165
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));
170
171   resizing_host_observer_.reset();
172   EXPECT_EQ(0, restore_resolution_call_count);
173 }
174
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, NULL, 0,
180                                &restore_resolution_call_count));
181   SetDesktopResizer(desktop_resizer.Pass());
182
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);
191 }
192
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                              NULL));
202   SetDesktopResizer(desktop_resizer.Pass());
203
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));
211 }
212
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                              NULL));
222   SetDesktopResizer(desktop_resizer.Pass());
223
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));
230 }
231
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                              NULL));
241   SetDesktopResizer(desktop_resizer.Pass());
242
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));
252 }
253
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   FakeDesktopResizer* desktop_resizer =
260       new FakeDesktopResizer(MakeResolution(480, 640), false,
261                              supported_sizes, arraysize(supported_sizes), NULL);
262   SetDesktopResizer(scoped_ptr<FakeDesktopResizer>(desktop_resizer));
263
264   ScreenResolution client_sizes[] = { MakeResolution(640, 640),
265                                       MakeResolution(1024, 768),
266                                       MakeResolution(640, 480) };
267   ScreenResolution expected_sizes[] = { MakeResolution(640, 480),
268                                         MakeResolution(640, 480),
269                                         MakeResolution(640, 480) };
270   VerifySizes(client_sizes, expected_sizes, arraysize(client_sizes));
271   EXPECT_EQ(desktop_resizer->set_resolution_call_count(), 1);
272 }
273
274 // Check that desktop resizes are rate-limited, and that if multiple resize
275 // requests are received in the time-out period, the most recent is respected.
276 TEST_F(ResizingHostObserverTest, RateLimited) {
277   FakeDesktopResizer* desktop_resizer =
278       new FakeDesktopResizer(MakeResolution(640, 480), true, NULL, 0, NULL);
279   SetDesktopResizer(scoped_ptr<FakeDesktopResizer>(desktop_resizer));
280   resizing_host_observer_->SetNowFunctionForTesting(
281       base::Bind(&ResizingHostObserverTest::GetTime, base::Unretained(this)));
282
283   base::MessageLoop message_loop;
284   base::RunLoop run_loop;
285
286   EXPECT_EQ(GetBestResolution(MakeResolution(100, 100)),
287             MakeResolution(100, 100));
288   now_ += base::TimeDelta::FromMilliseconds(900);
289   EXPECT_EQ(GetBestResolution(MakeResolution(200, 200)),
290             MakeResolution(100, 100));
291   now_ += base::TimeDelta::FromMilliseconds(99);
292   EXPECT_EQ(GetBestResolution(MakeResolution(300, 300)),
293             MakeResolution(100, 100));
294   now_ += base::TimeDelta::FromMilliseconds(1);
295
296   // Due to the kMinimumResizeIntervalMs constant in resizing_host_observer.cc,
297   // We need to wait a total of 1000ms for the final resize to be processed.
298   // Since it was queued 900 + 99 ms after the first, we need to wait an
299   // additional 1ms. However, since RunLoop is not guaranteed to process tasks
300   // with the same due time in FIFO order, wait an additional 1ms for safety.
301   message_loop.PostDelayedTask(
302       FROM_HERE,
303       run_loop.QuitClosure(),
304       base::TimeDelta::FromMilliseconds(2));
305   run_loop.Run();
306
307   // If the QuitClosure fired before the final resize, it's a test failure.
308   EXPECT_EQ(desktop_resizer_->GetCurrentResolution(), MakeResolution(300, 300));
309 }
310
311 }  // namespace remoting