Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / ui / display / chromeos / x11 / native_display_event_dispatcher_x11_unittest.cc
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 <X11/extensions/Xrandr.h>
6
7 #undef Bool
8 #undef None
9
10 #include "base/test/simple_test_tick_clock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/display/chromeos/x11/display_mode_x11.h"
13 #include "ui/display/chromeos/x11/display_snapshot_x11.h"
14 #include "ui/display/chromeos/x11/native_display_delegate_x11.h"
15 #include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
16
17 namespace ui {
18
19 namespace {
20
21 DisplaySnapshotX11* CreateOutput(RROutput output, RRCrtc crtc) {
22   static const DisplayModeX11* kDefaultDisplayMode =
23       new DisplayModeX11(gfx::Size(1, 1), false, 60.0f, 20);
24
25   DisplaySnapshotX11* snapshot = new DisplaySnapshotX11(
26       0,
27       false,
28       gfx::Point(0, 0),
29       gfx::Size(0, 0),
30       OUTPUT_TYPE_UNKNOWN,
31       false,
32       std::vector<const DisplayMode*>(1, kDefaultDisplayMode),
33       kDefaultDisplayMode,
34       NULL,
35       output,
36       crtc,
37       0);
38
39   return snapshot;
40 }
41
42 class TestHelperDelegate : public NativeDisplayDelegateX11::HelperDelegate {
43  public:
44   TestHelperDelegate();
45   virtual ~TestHelperDelegate();
46
47   int num_calls_update_xrandr_config() const {
48     return num_calls_update_xrandr_config_;
49   }
50
51   int num_calls_notify_observers() const { return num_calls_notify_observers_; }
52
53   void set_cached_outputs(const std::vector<DisplaySnapshot*>& outputs) {
54     cached_outputs_ = outputs;
55   }
56
57   // NativeDisplayDelegateX11::HelperDelegate overrides:
58   virtual void UpdateXRandRConfiguration(const base::NativeEvent& event)
59       OVERRIDE;
60   virtual const std::vector<DisplaySnapshot*>& GetCachedOutputs() const
61       OVERRIDE;
62   virtual void NotifyDisplayObservers() OVERRIDE;
63
64  private:
65   int num_calls_update_xrandr_config_;
66   int num_calls_notify_observers_;
67
68   std::vector<DisplaySnapshot*> cached_outputs_;
69
70   DISALLOW_COPY_AND_ASSIGN(TestHelperDelegate);
71 };
72
73 TestHelperDelegate::TestHelperDelegate()
74     : num_calls_update_xrandr_config_(0), num_calls_notify_observers_(0) {}
75
76 TestHelperDelegate::~TestHelperDelegate() {}
77
78 void TestHelperDelegate::UpdateXRandRConfiguration(
79     const base::NativeEvent& event) {
80   ++num_calls_update_xrandr_config_;
81 }
82
83 const std::vector<DisplaySnapshot*>& TestHelperDelegate::GetCachedOutputs()
84     const {
85   return cached_outputs_;
86 }
87
88 void TestHelperDelegate::NotifyDisplayObservers() {
89   ++num_calls_notify_observers_;
90 }
91
92 ////////////////////////////////////////////////////////////////////////////////
93 // NativeDisplayEventDispatcherX11Test
94
95 class NativeDisplayEventDispatcherX11Test : public testing::Test {
96  public:
97   NativeDisplayEventDispatcherX11Test();
98   virtual ~NativeDisplayEventDispatcherX11Test();
99
100  protected:
101   void DispatchScreenChangeEvent();
102   void DispatchOutputChangeEvent(RROutput output,
103                                  RRCrtc crtc,
104                                  RRMode mode,
105                                  bool connected);
106
107   int xrandr_event_base_;
108   scoped_ptr<TestHelperDelegate> helper_delegate_;
109   scoped_ptr<NativeDisplayEventDispatcherX11> dispatcher_;
110   base::SimpleTestTickClock* test_tick_clock_;  // Owned by |dispatcher_|.
111
112  private:
113   DISALLOW_COPY_AND_ASSIGN(NativeDisplayEventDispatcherX11Test);
114 };
115
116 NativeDisplayEventDispatcherX11Test::NativeDisplayEventDispatcherX11Test()
117     : xrandr_event_base_(10),
118       helper_delegate_(new TestHelperDelegate()),
119       dispatcher_(new NativeDisplayEventDispatcherX11(helper_delegate_.get(),
120                                                       xrandr_event_base_)),
121       test_tick_clock_(new base::SimpleTestTickClock) {
122   test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1));
123   dispatcher_->SetTickClockForTest(
124       scoped_ptr<base::TickClock>(test_tick_clock_));
125 }
126
127 NativeDisplayEventDispatcherX11Test::~NativeDisplayEventDispatcherX11Test() {}
128
129 void NativeDisplayEventDispatcherX11Test::DispatchScreenChangeEvent() {
130   XRRScreenChangeNotifyEvent event = {0};
131   event.type = xrandr_event_base_ + RRScreenChangeNotify;
132
133   dispatcher_->Dispatch(reinterpret_cast<const base::NativeEvent>(&event));
134 }
135
136 void NativeDisplayEventDispatcherX11Test::DispatchOutputChangeEvent(
137     RROutput output,
138     RRCrtc crtc,
139     RRMode mode,
140     bool connected) {
141   XRROutputChangeNotifyEvent event = {0};
142   event.type = xrandr_event_base_ + RRNotify;
143   event.subtype = RRNotify_OutputChange;
144   event.output = output;
145   event.crtc = crtc;
146   event.mode = mode;
147   event.connection = connected ? RR_Connected : RR_Disconnected;
148
149   dispatcher_->Dispatch(reinterpret_cast<const base::NativeEvent>(&event));
150 }
151
152 }  // namespace
153
154 TEST_F(NativeDisplayEventDispatcherX11Test, OnScreenChangedEvent) {
155   DispatchScreenChangeEvent();
156   EXPECT_EQ(1, helper_delegate_->num_calls_update_xrandr_config());
157   EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
158 }
159
160 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnFirstEvent) {
161   DispatchOutputChangeEvent(1, 10, 20, true);
162   EXPECT_EQ(0, helper_delegate_->num_calls_update_xrandr_config());
163   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
164 }
165
166 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationAfterSecondEvent) {
167   DispatchOutputChangeEvent(1, 10, 20, true);
168
169   // Simulate addition of the first output to the cached output list.
170   ScopedVector<DisplaySnapshot> outputs;
171   outputs.push_back(CreateOutput(1, 10));
172   helper_delegate_->set_cached_outputs(outputs.get());
173
174   DispatchOutputChangeEvent(2, 11, 20, true);
175   EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
176 }
177
178 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDisconnect) {
179   ScopedVector<DisplaySnapshot> outputs;
180   outputs.push_back(CreateOutput(1, 10));
181   helper_delegate_->set_cached_outputs(outputs.get());
182
183   DispatchOutputChangeEvent(1, 10, 20, false);
184   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
185 }
186
187 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnModeChange) {
188   ScopedVector<DisplaySnapshot> outputs;
189   outputs.push_back(CreateOutput(1, 10));
190   helper_delegate_->set_cached_outputs(outputs.get());
191
192   DispatchOutputChangeEvent(1, 10, 21, true);
193   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
194 }
195
196 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnSecondOutput) {
197   ScopedVector<DisplaySnapshot> outputs;
198   outputs.push_back(CreateOutput(1, 10));
199   helper_delegate_->set_cached_outputs(outputs.get());
200
201   DispatchOutputChangeEvent(2, 11, 20, true);
202   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
203 }
204
205 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDifferentCrtc) {
206   ScopedVector<DisplaySnapshot> outputs;
207   outputs.push_back(CreateOutput(1, 10));
208   helper_delegate_->set_cached_outputs(outputs.get());
209
210   DispatchOutputChangeEvent(1, 11, 20, true);
211   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
212 }
213
214 TEST_F(NativeDisplayEventDispatcherX11Test,
215        CheckNotificationOnSecondOutputDisconnect) {
216   ScopedVector<DisplaySnapshot> outputs;
217   outputs.push_back(CreateOutput(1, 10));
218   outputs.push_back(CreateOutput(2, 11));
219   helper_delegate_->set_cached_outputs(outputs.get());
220
221   DispatchOutputChangeEvent(2, 11, 20, false);
222   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
223 }
224
225 TEST_F(NativeDisplayEventDispatcherX11Test,
226        AvoidDuplicateNotificationOnSecondOutputDisconnect) {
227   ScopedVector<DisplaySnapshot> outputs;
228   outputs.push_back(CreateOutput(1, 10));
229   outputs.push_back(CreateOutput(2, 11));
230   helper_delegate_->set_cached_outputs(outputs.get());
231
232   DispatchOutputChangeEvent(2, 11, 20, false);
233   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
234
235   // Simulate removal of second output from cached output list.
236   outputs.erase(outputs.begin() + 1);
237   helper_delegate_->set_cached_outputs(outputs.get());
238
239   DispatchOutputChangeEvent(2, 11, 20, false);
240   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
241 }
242
243 TEST_F(NativeDisplayEventDispatcherX11Test,
244        ForceUpdateAfterCacheExpiration) {
245   // +1 to compenstate a possible rounding error.
246   const int kHalfOfExpirationMs =
247       NativeDisplayEventDispatcherX11::kUseCacheAfterStartupMs / 2 + 1;
248
249   ScopedVector<DisplaySnapshot> outputs;
250   outputs.push_back(CreateOutput(1, 10));
251   outputs.push_back(CreateOutput(2, 11));
252   helper_delegate_->set_cached_outputs(outputs.get());
253
254   EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
255
256   // Duplicated event will be ignored during the startup.
257   DispatchOutputChangeEvent(2, 11, 20, true);
258   EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
259
260   test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
261       kHalfOfExpirationMs));
262
263   // Duplicated event will still be ignored.
264   DispatchOutputChangeEvent(2, 11, 20, true);
265   EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
266
267   // The startup timeout has been elapsed. Duplicated event
268   // should not be ignored.
269   test_tick_clock_->Advance(
270       base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
271   DispatchOutputChangeEvent(2, 11, 20, true);
272   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
273
274   // Sending the same event immediately shoudldn't be ignored.
275   DispatchOutputChangeEvent(2, 11, 20, true);
276   EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
277
278   // Advancing time further should not change the behavior.
279   test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
280       kHalfOfExpirationMs));
281   DispatchOutputChangeEvent(2, 11, 20, true);
282   EXPECT_EQ(3, helper_delegate_->num_calls_notify_observers());
283
284   test_tick_clock_->Advance(
285       base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
286   DispatchOutputChangeEvent(2, 11, 20, true);
287   EXPECT_EQ(4, helper_delegate_->num_calls_notify_observers());
288 }
289
290 }  // namespace ui