Chromium Code Reviews| 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 |