OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 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/events/event_rewriter.h" | |
6 | |
7 #include <list> | |
8 #include <map> | |
9 #include <set> | |
10 #include <utility> | |
11 | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 #include "ui/events/test/test_event_processor.h" | |
14 | |
15 namespace ui { | |
16 | |
17 namespace { | |
18 | |
19 // To test the handling of |EventRewriter|s through |EventSource|, | |
20 // we change and test event type. | |
21 | |
22 // TestEventRewriteProcessor is set up with a sequence of event types, | |
23 // and fails if the events received via OnEventFromSource() do not match | |
24 // this sequence. These expected event types are consumed on receipt. | |
25 class TestEventRewriteProcessor : public test::TestEventProcessor { | |
26 public: | |
27 ~TestEventRewriteProcessor() { CheckAllReceived(); } | |
sadrul
2014/03/24 21:15:38
virtual
| |
28 | |
29 // EventProcessor: | |
30 virtual EventDispatchDetails OnEventFromSource(Event* event) OVERRIDE { | |
sadrul
2014/03/24 21:15:38
Overrides typically go at the end of the block. So
| |
31 EXPECT_FALSE(expected_events_.empty()); | |
32 EXPECT_EQ(expected_events_.front(), event->type()); | |
33 expected_events_.pop_front(); | |
34 return EventDispatchDetails(); | |
35 } | |
36 | |
37 void AddExpectedEvent(EventType type) { expected_events_.push_back(type); } | |
38 // Test that all expected events have been received. | |
39 void CheckAllReceived() { EXPECT_TRUE(expected_events_.empty()); } | |
40 | |
41 private: | |
42 std::list<EventType> expected_events_; | |
sadrul
2014/03/24 21:15:38
DISALLOW_COPY_AND_ASSIGN
| |
43 }; | |
44 | |
45 // Allocates events, testing that none are leaked. | |
46 class TestEventFactory { | |
47 public: | |
48 TestEventFactory() {} | |
49 ~TestEventFactory() { EXPECT_TRUE(events_.empty()); } | |
50 | |
51 Event* New(EventType type) { | |
sadrul
2014/03/24 21:15:38
This should return a scoped_ptr<>
| |
52 Event* event = new TestEvent(*this, type); | |
53 EXPECT_TRUE(event); | |
54 events_.insert(event); | |
55 return event; | |
56 } | |
57 void Check(Event* event) { EXPECT_NE(events_.end(), events_.find(event)); } | |
58 void Delete(Event* event) { | |
59 EventList::iterator find = events_.find(event); | |
60 EXPECT_NE(events_.end(), find); | |
61 events_.erase(find); | |
62 } | |
63 | |
64 private: | |
65 class TestEvent : public Event { | |
66 public: | |
67 TestEvent(TestEventFactory& factory, EventType type) | |
68 : Event(type, base::TimeDelta(), 0), factory_(factory) {} | |
69 ~TestEvent() { factory_.Delete(this); } | |
70 | |
71 private: | |
72 TestEventFactory& factory_; | |
73 }; | |
74 typedef std::set<Event*> EventList; | |
75 EventList events_; | |
76 DISALLOW_COPY_AND_ASSIGN(TestEventFactory); | |
77 }; | |
78 | |
79 // Trivial EventSource that does nothing but send events. | |
80 class TestEventRewriteSource : public EventSource { | |
81 public: | |
82 explicit TestEventRewriteSource(EventProcessor* processor) | |
83 : processor_(processor) {} | |
84 virtual EventProcessor* GetEventProcessor() OVERRIDE { return processor_; } | |
85 void Send(EventType type) { | |
86 scoped_ptr<Event> event(event_factory_.New(type)); | |
87 (void)SendEventToProcessor(event.get()); | |
sadrul
2014/03/24 21:15:38
You don't need to Delete the event in the event-fa
| |
88 } | |
89 | |
90 private: | |
91 TestEventFactory event_factory_; | |
92 EventProcessor* processor_; | |
93 }; | |
94 | |
95 // This EventRewriter always returns the same status; it is used to test | |
96 // simple rewriting, and rewriter addition, removal, and sequencing. | |
97 // EVENT_REWRITE_DISPATCH_ANOTHER is not supported here. | |
98 class TestConstantEventRewriter : public EventRewriter { | |
99 public: | |
100 TestConstantEventRewriter(EventRewriteStatus status, EventType type) | |
101 : status_(status), type_(type) { | |
102 EXPECT_NE(EVENT_REWRITE_DISPATCH_ANOTHER, status); | |
sadrul
2014/03/24 21:15:38
CHECK instead
| |
103 } | |
104 | |
105 virtual EventRewriteStatus RewriteEvent(const Event& event, | |
106 Event** rewritten_event) OVERRIDE { | |
107 EXPECT_TRUE(rewritten_event); | |
108 if (status_ == EVENT_REWRITE_REWRITTEN) { | |
109 *rewritten_event = event_factory_.New(type_); | |
110 } | |
111 return status_; | |
112 } | |
113 virtual EventRewriteStatus NextDispatchEvent(const Event& last_event, | |
114 Event** new_event) OVERRIDE { | |
115 EXPECT_TRUE(false); | |
sadrul
2014/03/24 21:15:38
Replace this with a NOTREACHED instead
| |
116 return status_; | |
117 } | |
118 | |
119 private: | |
120 EventRewriteStatus status_; | |
121 EventType type_; | |
122 TestEventFactory event_factory_; | |
123 }; | |
124 | |
125 // This EventRewriter runs a simple state machine; it is used to test | |
126 // EVENT_REWRITE_DISPATCH_ANOTHER. | |
127 class TestStateMachineEventRewriter : public EventRewriter { | |
128 public: | |
129 TestStateMachineEventRewriter() : state_(0), last_rewritten_event_(0) {} | |
130 void AddRule(int from_state, EventType from_type, | |
131 int to_state, EventType to_type, EventRewriteStatus to_status) { | |
132 RewriteResult r = {to_state, to_type, to_status}; | |
133 rules_.insert(std::pair<RewriteCase, RewriteResult>( | |
134 RewriteCase(from_state, from_type), r)); | |
135 } | |
136 virtual EventRewriteStatus RewriteEvent(const Event& event, | |
137 Event** rewritten_event) OVERRIDE { | |
138 EXPECT_TRUE(rewritten_event); | |
139 RewriteRules::iterator find = | |
140 rules_.find(RewriteCase(state_, event.type())); | |
141 if (find == rules_.end()) { | |
142 return EVENT_REWRITE_CONTINUE; | |
143 } | |
144 if ((find->second.status == EVENT_REWRITE_REWRITTEN) || | |
145 (find->second.status == EVENT_REWRITE_DISPATCH_ANOTHER)) { | |
146 last_rewritten_event_ = event_factory_.New(find->second.type); | |
147 *rewritten_event = last_rewritten_event_; | |
148 } | |
149 state_ = find->second.state; | |
150 return find->second.status; | |
151 } | |
152 virtual EventRewriteStatus NextDispatchEvent(const Event& last_event, | |
153 Event** new_event) OVERRIDE { | |
154 EXPECT_TRUE(last_rewritten_event_); | |
155 EXPECT_EQ(last_rewritten_event_->type(), last_event.type()); | |
156 event_factory_.Check(last_rewritten_event_); | |
sadrul
2014/03/24 21:15:38
We should add a unique-identifer for each TestEven
kpschoedel
2014/03/25 18:12:01
Is it really necessary to pass back last_event? If
sadrul
2014/03/25 18:24:35
I am thinking the rewriter will need to maintain l
| |
157 last_rewritten_event_ = 0; | |
158 return RewriteEvent(last_event, new_event); | |
159 } | |
160 | |
161 private: | |
162 typedef std::pair<int, EventType> RewriteCase; | |
163 struct RewriteResult { | |
164 int state; | |
165 EventType type; | |
166 EventRewriteStatus status; | |
167 }; | |
168 typedef std::map<RewriteCase, RewriteResult> RewriteRules; | |
169 | |
170 int state_; | |
171 RewriteRules rules_; | |
172 TestEventFactory event_factory_; | |
173 Event* last_rewritten_event_; | |
174 }; | |
175 | |
176 } // namespace | |
177 | |
178 TEST(EventRewriterTest, EventRewriting) { | |
179 // TestEventRewriter r0 always rewrites events to ET_CANCEL_MODE; | |
180 // it is placed at the beginning of the chain and later removed, | |
181 // to verify that rewriter removal works. | |
182 TestConstantEventRewriter r0(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE); | |
183 | |
184 // TestEventRewriter r1 always returns EVENT_REWRITE_CONTINUE; | |
185 // it is placed at the beginning of the chain to verify that a | |
186 // later rewriter sees the events. | |
187 TestConstantEventRewriter r1(EVENT_REWRITE_CONTINUE, ET_UNKNOWN); | |
188 | |
189 // TestEventRewriter r2 has a state machine, primarily to test | |
190 // |EVENT_REWRITE_DISPATCH_ANOTHER|. | |
191 TestStateMachineEventRewriter r2; | |
192 | |
193 // TestEventRewriter r3 always rewrites events to ET_CANCEL_MODE; | |
194 // it is placed at the end of the chain to verify that previously | |
195 // rewritten events are not passed further down the chain. | |
196 TestConstantEventRewriter r3(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE); | |
197 | |
198 TestEventRewriteProcessor p; | |
199 TestEventRewriteSource s(&p); | |
200 s.AddEventRewriter(&r0); | |
201 s.AddEventRewriter(&r1); | |
202 s.AddEventRewriter(&r2); | |
203 | |
204 // These events should be rewritten by r0 to ET_CANCEL_MODE. | |
205 p.AddExpectedEvent(ET_CANCEL_MODE); | |
206 s.Send(ET_MOUSE_DRAGGED); | |
207 p.AddExpectedEvent(ET_CANCEL_MODE); | |
208 s.Send(ET_MOUSE_PRESSED); | |
209 p.CheckAllReceived(); | |
210 | |
211 // Remove r0, and verify that it's gone and that events make it through. | |
212 s.AddEventRewriter(&r3); | |
213 s.RemoveEventRewriter(&r0); | |
214 r2.AddRule(0, ET_SCROLL_FLING_START, | |
215 0, ET_SCROLL_FLING_CANCEL, EVENT_REWRITE_REWRITTEN); | |
216 p.AddExpectedEvent(ET_SCROLL_FLING_CANCEL); | |
217 s.Send(ET_SCROLL_FLING_START); | |
218 p.CheckAllReceived(); | |
219 s.RemoveEventRewriter(&r3); | |
220 | |
221 // Verify EVENT_REWRITE_DISPATCH_ANOTHER using a state machine | |
222 // (that happens to be analogous to sticky keys). | |
223 r2.AddRule(0, ET_KEY_PRESSED, | |
224 1, ET_KEY_PRESSED, EVENT_REWRITE_CONTINUE); | |
225 r2.AddRule(1, ET_MOUSE_PRESSED, | |
226 0, ET_MOUSE_PRESSED, EVENT_REWRITE_CONTINUE); | |
227 r2.AddRule(1, ET_KEY_RELEASED, | |
228 2, ET_KEY_RELEASED, EVENT_REWRITE_DISCARD); | |
229 r2.AddRule(2, ET_MOUSE_RELEASED, | |
230 3, ET_MOUSE_RELEASED, | |
231 EVENT_REWRITE_DISPATCH_ANOTHER); | |
232 r2.AddRule(3, ET_MOUSE_RELEASED, 0, | |
233 ET_KEY_RELEASED, EVENT_REWRITE_REWRITTEN); | |
234 p.AddExpectedEvent(ET_KEY_PRESSED); | |
235 s.Send(ET_KEY_PRESSED); | |
236 s.Send(ET_KEY_RELEASED); | |
237 p.AddExpectedEvent(ET_MOUSE_PRESSED); | |
238 s.Send(ET_MOUSE_PRESSED); | |
239 | |
240 // Removing rewriters r1 and r3 shouldn't affect r2. | |
241 s.RemoveEventRewriter(&r1); | |
242 s.RemoveEventRewriter(&r3); | |
243 | |
244 // Continue with the state-based rewriting. | |
245 p.AddExpectedEvent(ET_MOUSE_RELEASED); | |
246 p.AddExpectedEvent(ET_KEY_RELEASED); | |
247 s.Send(ET_MOUSE_RELEASED); | |
248 p.CheckAllReceived(); | |
249 } | |
250 | |
251 } // namespace ui | |
OLD | NEW |