1// Copyright 2014 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 "ui/gfx/display_change_notifier.h"
6
7#include "testing/gtest/include/gtest/gtest.h"
8#include "ui/gfx/display.h"
9#include "ui/gfx/display_observer.h"
10
11namespace gfx {
12
13class MockDisplayObserver : public DisplayObserver {
14 public:
15  MockDisplayObserver()
16    : display_added_(0),
17      display_removed_(0),
18      display_changed_(0),
19      latest_metrics_change_(DisplayObserver::DISPLAY_METRIC_NONE)
20  {}
21
22  virtual ~MockDisplayObserver() { }
23
24  virtual void OnDisplayAdded(const Display& display) OVERRIDE {
25    display_added_++;
26  }
27
28  virtual void OnDisplayRemoved(const Display& display) OVERRIDE {
29    display_removed_++;
30  }
31
32  virtual void OnDisplayMetricsChanged(const Display& display,
33                                       uint32_t metrics) OVERRIDE {
34    display_changed_++;
35    latest_metrics_change_ = metrics;
36  }
37
38  int display_added() const {
39    return display_added_;
40  }
41
42  int display_removed() const {
43    return display_removed_;
44  }
45
46  int display_changed() const {
47    return display_changed_;
48  }
49
50  uint32_t latest_metrics_change() const {
51    return latest_metrics_change_;
52  }
53
54 protected:
55  int display_added_;
56  int display_removed_;
57  int display_changed_;
58  uint32_t latest_metrics_change_;
59
60  DISALLOW_COPY_AND_ASSIGN(MockDisplayObserver);
61};
62
63TEST(DisplayChangeNotifierTest, AddObserver_Smoke) {
64  DisplayChangeNotifier change_notifier;
65  MockDisplayObserver observer;
66
67  change_notifier.NotifyDisplaysChanged(
68    std::vector<Display>(), std::vector<Display>(1, Display()));
69  EXPECT_EQ(0, observer.display_added());
70
71  change_notifier.AddObserver(&observer);
72  change_notifier.NotifyDisplaysChanged(
73    std::vector<Display>(), std::vector<Display>(1, Display()));
74  EXPECT_EQ(1, observer.display_added());
75}
76
77TEST(DisplayChangeNotifierTest, AddObserver_Null) {
78  DisplayChangeNotifier change_notifier;
79
80  change_notifier.AddObserver(NULL);
81  // Should not crash.
82}
83
84TEST(DisplayChangeNotifier, RemoveObserver_Smoke) {
85  DisplayChangeNotifier change_notifier;
86  MockDisplayObserver observer;
87
88  change_notifier.NotifyDisplaysChanged(
89    std::vector<Display>(), std::vector<Display>(1, Display()));
90  EXPECT_EQ(0, observer.display_added());
91
92  change_notifier.AddObserver(&observer);
93  change_notifier.RemoveObserver(&observer);
94
95  change_notifier.NotifyDisplaysChanged(
96    std::vector<Display>(), std::vector<Display>(1, Display()));
97  EXPECT_EQ(0, observer.display_added());
98}
99
100TEST(DisplayChangeNotifierTest, RemoveObserver_Null) {
101  DisplayChangeNotifier change_notifier;
102
103  change_notifier.RemoveObserver(NULL);
104  // Should not crash.
105}
106
107TEST(DisplayChangeNotifierTest, RemoveObserver_Unknown) {
108  DisplayChangeNotifier change_notifier;
109  MockDisplayObserver observer;
110
111  change_notifier.RemoveObserver(&observer);
112  // Should not crash.
113}
114
115TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Removed) {
116  DisplayChangeNotifier change_notifier;
117
118  // If the previous display array is empty, no removal.
119  {
120    MockDisplayObserver observer;
121    change_notifier.AddObserver(&observer);
122
123    std::vector<Display> old_displays, new_displays;
124    new_displays.push_back(Display());
125
126    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
127    EXPECT_EQ(0, observer.display_removed());
128
129    change_notifier.RemoveObserver(&observer);
130  }
131
132  // If the previous and new display array are empty, no removal.
133  {
134    MockDisplayObserver observer;
135    change_notifier.AddObserver(&observer);
136
137    std::vector<Display> old_displays, new_displays;
138
139    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
140    EXPECT_EQ(0, observer.display_removed());
141
142    change_notifier.RemoveObserver(&observer);
143  }
144
145  // If the new display array is empty, there are as many removal as old
146  // displays.
147  {
148    MockDisplayObserver observer;
149    change_notifier.AddObserver(&observer);
150
151    std::vector<Display> old_displays, new_displays;
152    old_displays.push_back(Display());
153    old_displays.push_back(Display());
154    old_displays.push_back(Display());
155
156    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
157    EXPECT_EQ(3, observer.display_removed());
158
159    change_notifier.RemoveObserver(&observer);
160  }
161
162  // If displays don't use ids, as long as the new display array has one
163  // element, there are no removals.
164  {
165    MockDisplayObserver observer;
166    change_notifier.AddObserver(&observer);
167
168    std::vector<Display> old_displays, new_displays;
169    old_displays.push_back(Display());
170    old_displays.push_back(Display());
171    old_displays.push_back(Display());
172    new_displays.push_back(Display());
173
174    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
175    EXPECT_EQ(0, observer.display_removed());
176
177    change_notifier.RemoveObserver(&observer);
178  }
179
180  // If displays use ids (and they are unique), ids not present in the new
181  // display array will be marked as removed.
182  {
183    MockDisplayObserver observer;
184    change_notifier.AddObserver(&observer);
185
186    std::vector<Display> old_displays, new_displays;
187    old_displays.push_back(Display(1));
188    old_displays.push_back(Display(2));
189    old_displays.push_back(Display(3));
190    new_displays.push_back(Display(2));
191
192    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
193    EXPECT_EQ(2, observer.display_removed());
194
195    change_notifier.RemoveObserver(&observer);
196  }
197}
198
199TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Added) {
200  DisplayChangeNotifier change_notifier;
201
202  // If the new display array is empty, no addition.
203  {
204    MockDisplayObserver observer;
205    change_notifier.AddObserver(&observer);
206
207    std::vector<Display> old_displays, new_displays;
208    old_displays.push_back(Display());
209
210    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
211    EXPECT_EQ(0, observer.display_added());
212
213    change_notifier.RemoveObserver(&observer);
214  }
215
216  // If the old and new display arrays are empty, no addition.
217  {
218    MockDisplayObserver observer;
219    change_notifier.AddObserver(&observer);
220
221    std::vector<Display> old_displays, new_displays;
222
223    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
224    EXPECT_EQ(0, observer.display_added());
225
226    change_notifier.RemoveObserver(&observer);
227  }
228
229  // If the old display array is empty, there are as many addition as new
230  // displays.
231  {
232    MockDisplayObserver observer;
233    change_notifier.AddObserver(&observer);
234
235    std::vector<Display> old_displays, new_displays;
236    new_displays.push_back(Display());
237    new_displays.push_back(Display());
238    new_displays.push_back(Display());
239
240    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
241    EXPECT_EQ(3, observer.display_added());
242
243    change_notifier.RemoveObserver(&observer);
244  }
245
246  // If displays don't use ids, as long as the old display array has one
247  // element, there are no additions.
248  {
249    MockDisplayObserver observer;
250    change_notifier.AddObserver(&observer);
251
252    std::vector<Display> old_displays, new_displays;
253    old_displays.push_back(Display());
254    new_displays.push_back(Display());
255    new_displays.push_back(Display());
256    new_displays.push_back(Display());
257
258    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
259    EXPECT_EQ(0, observer.display_added());
260
261    change_notifier.RemoveObserver(&observer);
262  }
263
264  // If displays use ids (and they are unique), ids not present in the old
265  // display array will be marked as added.
266  {
267    MockDisplayObserver observer;
268    change_notifier.AddObserver(&observer);
269
270    std::vector<Display> old_displays, new_displays;
271    old_displays.push_back(Display(1));
272    new_displays.push_back(Display(1));
273    new_displays.push_back(Display(2));
274    new_displays.push_back(Display(3));
275
276    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
277    EXPECT_EQ(2, observer.display_added());
278
279    change_notifier.RemoveObserver(&observer);
280  }
281}
282
283TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Smoke) {
284  DisplayChangeNotifier change_notifier;
285
286  // If the old display array is empty, no change.
287  {
288    MockDisplayObserver observer;
289    change_notifier.AddObserver(&observer);
290
291    std::vector<Display> old_displays, new_displays;
292    new_displays.push_back(Display());
293
294    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
295    EXPECT_EQ(0, observer.display_changed());
296
297    change_notifier.RemoveObserver(&observer);
298  }
299
300  // If the new display array is empty, no change.
301  {
302    MockDisplayObserver observer;
303    change_notifier.AddObserver(&observer);
304
305    std::vector<Display> old_displays, new_displays;
306    old_displays.push_back(Display());
307
308    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
309    EXPECT_EQ(0, observer.display_changed());
310
311    change_notifier.RemoveObserver(&observer);
312  }
313
314  // If the old and new display arrays are empty, no change.
315  {
316    MockDisplayObserver observer;
317    change_notifier.AddObserver(&observer);
318
319    std::vector<Display> old_displays, new_displays;
320
321    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
322    EXPECT_EQ(0, observer.display_changed());
323
324    change_notifier.RemoveObserver(&observer);
325  }
326
327  // If there is an intersection between old and new displays but there are no
328  // metrics changes, there is no display change.
329  {
330    MockDisplayObserver observer;
331    change_notifier.AddObserver(&observer);
332
333    std::vector<Display> old_displays, new_displays;
334    old_displays.push_back(Display(1));
335    new_displays.push_back(Display(1));
336    new_displays.push_back(Display(2));
337    new_displays.push_back(Display(3));
338
339    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
340    EXPECT_EQ(0, observer.display_changed());
341
342    change_notifier.RemoveObserver(&observer);
343  }
344}
345
346TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Bounds) {
347  DisplayChangeNotifier change_notifier;
348
349  {
350    MockDisplayObserver observer;
351    change_notifier.AddObserver(&observer);
352
353    std::vector<Display> old_displays, new_displays;
354    old_displays.push_back(Display(1, Rect(0, 0, 200, 200)));
355    new_displays.push_back(Display(1, Rect(0, 0, 200, 200)));
356
357    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
358    EXPECT_EQ(0, observer.display_changed());
359
360    change_notifier.RemoveObserver(&observer);
361  }
362
363  {
364    MockDisplayObserver observer;
365    change_notifier.AddObserver(&observer);
366
367    std::vector<Display> old_displays, new_displays;
368    old_displays.push_back(Display(1, Rect(0, 0, 200, 200)));
369    new_displays.push_back(Display(1, Rect(10, 10, 300, 300)));
370
371    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
372    EXPECT_EQ(1, observer.display_changed());
373    uint32_t metrics_change = DisplayObserver::DISPLAY_METRIC_BOUNDS |
374                                  DisplayObserver::DISPLAY_METRIC_WORK_AREA;
375    EXPECT_EQ(metrics_change, observer.latest_metrics_change());
376
377    change_notifier.RemoveObserver(&observer);
378  }
379
380  {
381    MockDisplayObserver observer;
382    change_notifier.AddObserver(&observer);
383
384    std::vector<Display> old_displays, new_displays;
385    old_displays.push_back(Display(1, Rect(0, 0, 200, 200)));
386    new_displays.push_back(Display(1, Rect(0, 0, 200, 200)));
387    new_displays[0].set_bounds(Rect(10, 10, 300, 300));
388
389    change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
390    EXPECT_EQ(1, observer.display_changed());
391    EXPECT_EQ(DisplayObserver::DISPLAY_METRIC_BOUNDS,
392              observer.latest_metrics_change());
393
394    change_notifier.RemoveObserver(&observer);
395  }
396}
397
398TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Rotation) {
399  DisplayChangeNotifier change_notifier;
400  MockDisplayObserver observer;
401  change_notifier.AddObserver(&observer);
402
403  std::vector<Display> old_displays, new_displays;
404  old_displays.push_back(Display(1));
405  old_displays[0].SetRotationAsDegree(0);
406  new_displays.push_back(Display(1));
407  new_displays[0].SetRotationAsDegree(180);
408
409  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
410  EXPECT_EQ(1, observer.display_changed());
411  EXPECT_EQ(DisplayObserver::DISPLAY_METRIC_ROTATION,
412            observer.latest_metrics_change());
413}
414
415TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_WorkArea) {
416  DisplayChangeNotifier change_notifier;
417  MockDisplayObserver observer;
418  change_notifier.AddObserver(&observer);
419
420  std::vector<Display> old_displays, new_displays;
421  old_displays.push_back(Display(1));
422  old_displays[0].set_work_area(Rect(0, 0, 200, 200));
423  new_displays.push_back(Display(1));
424  new_displays[0].set_work_area(Rect(20, 20, 300, 300));
425
426  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
427  EXPECT_EQ(1, observer.display_changed());
428  EXPECT_EQ(DisplayObserver::DISPLAY_METRIC_WORK_AREA,
429            observer.latest_metrics_change());
430}
431
432TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_DSF) {
433  DisplayChangeNotifier change_notifier;
434  MockDisplayObserver observer;
435  change_notifier.AddObserver(&observer);
436
437  std::vector<Display> old_displays, new_displays;
438  old_displays.push_back(Display(1));
439  old_displays[0].set_device_scale_factor(1.f);
440  new_displays.push_back(Display(1));
441  new_displays[0].set_device_scale_factor(2.f);
442
443  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
444  EXPECT_EQ(1, observer.display_changed());
445  EXPECT_EQ(DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR,
446            observer.latest_metrics_change());
447}
448
449TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Multi_Displays) {
450  DisplayChangeNotifier change_notifier;
451  MockDisplayObserver observer;
452  change_notifier.AddObserver(&observer);
453
454  std::vector<Display> old_displays, new_displays;
455  old_displays.push_back(Display(1));
456  old_displays.push_back(Display(2));
457  old_displays.push_back(Display(3));
458  new_displays.push_back(Display(1));
459  new_displays.push_back(Display(2));
460  new_displays.push_back(Display(3));
461
462  old_displays[0].set_device_scale_factor(1.f);
463  new_displays[0].set_device_scale_factor(2.f);
464
465  old_displays[1].set_bounds(Rect(0, 0, 200, 200));
466  new_displays[1].set_bounds(Rect(0, 0, 400, 400));
467
468  old_displays[2].SetRotationAsDegree(0);
469  new_displays[2].SetRotationAsDegree(90);
470
471  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
472  EXPECT_EQ(3, observer.display_changed());
473}
474
475TEST(DisplayChangeNotifierTest, NotifyDisplaysChanged_Changed_Multi_Metrics) {
476  DisplayChangeNotifier change_notifier;
477  MockDisplayObserver observer;
478  change_notifier.AddObserver(&observer);
479
480  std::vector<Display> old_displays, new_displays;
481  old_displays.push_back(Display(1, Rect(0, 0, 200, 200)));
482  old_displays[0].set_device_scale_factor(1.f);
483  old_displays[0].SetRotationAsDegree(0);
484
485  new_displays.push_back(Display(1, Rect(100, 100, 200, 200)));
486  new_displays[0].set_device_scale_factor(2.f);
487  new_displays[0].SetRotationAsDegree(90);
488
489  change_notifier.NotifyDisplaysChanged(old_displays, new_displays);
490  EXPECT_EQ(1, observer.display_changed());
491  uint32_t metrics = DisplayObserver::DISPLAY_METRIC_BOUNDS |
492                         DisplayObserver::DISPLAY_METRIC_ROTATION |
493                         DisplayObserver::DISPLAY_METRIC_WORK_AREA |
494                         DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
495  EXPECT_EQ(metrics, observer.latest_metrics_change());
496}
497
498} // namespace gfx
499