event_rewriter_unittest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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/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 15namespace ui { 16 17namespace { 18 19// To test the handling of |EventRewriter|s through |EventSource|, 20// we rewrite and test event types. 21class TestEvent : public Event { 22 public: 23 explicit TestEvent(EventType type) 24 : Event(type, base::TimeDelta(), 0), unique_id_(next_unique_id_++) {} 25 virtual ~TestEvent() {} 26 int unique_id() const { return unique_id_; } 27 28 private: 29 static int next_unique_id_; 30 int unique_id_; 31}; 32 33int TestEvent::next_unique_id_ = 0; 34 35// TestEventRewriteProcessor is set up with a sequence of event types, 36// and fails if the events received via OnEventFromSource() do not match 37// this sequence. These expected event types are consumed on receipt. 38class TestEventRewriteProcessor : public test::TestEventProcessor { 39 public: 40 TestEventRewriteProcessor() {} 41 virtual ~TestEventRewriteProcessor() { CheckAllReceived(); } 42 43 void AddExpectedEvent(EventType type) { expected_events_.push_back(type); } 44 // Test that all expected events have been received. 45 void CheckAllReceived() { EXPECT_TRUE(expected_events_.empty()); } 46 47 // EventProcessor: 48 virtual EventDispatchDetails OnEventFromSource(Event* event) OVERRIDE { 49 EXPECT_FALSE(expected_events_.empty()); 50 EXPECT_EQ(expected_events_.front(), event->type()); 51 expected_events_.pop_front(); 52 return EventDispatchDetails(); 53 } 54 55 private: 56 std::list<EventType> expected_events_; 57 DISALLOW_COPY_AND_ASSIGN(TestEventRewriteProcessor); 58}; 59 60// Trivial EventSource that does nothing but send events. 61class TestEventRewriteSource : public EventSource { 62 public: 63 explicit TestEventRewriteSource(EventProcessor* processor) 64 : processor_(processor) {} 65 virtual EventProcessor* GetEventProcessor() OVERRIDE { return processor_; } 66 void Send(EventType type) { 67 scoped_ptr<Event> event(new TestEvent(type)); 68 (void)SendEventToProcessor(event.get()); 69 } 70 71 private: 72 EventProcessor* processor_; 73}; 74 75// This EventRewriter always returns the same status, and if rewriting, the 76// same event type; it is used to test simple rewriting, and rewriter addition, 77// removal, and sequencing. Consequently EVENT_REWRITE_DISPATCH_ANOTHER is not 78// supported here (calls to NextDispatchEvent() would continue indefinitely). 79class TestConstantEventRewriter : public EventRewriter { 80 public: 81 TestConstantEventRewriter(EventRewriteStatus status, EventType type) 82 : status_(status), type_(type) { 83 CHECK_NE(EVENT_REWRITE_DISPATCH_ANOTHER, status); 84 } 85 86 virtual EventRewriteStatus RewriteEvent(const Event& event, 87 scoped_ptr<Event>* rewritten_event) 88 OVERRIDE { 89 if (status_ == EVENT_REWRITE_REWRITTEN) 90 rewritten_event->reset(new TestEvent(type_)); 91 return status_; 92 } 93 virtual EventRewriteStatus NextDispatchEvent(const Event& last_event, 94 scoped_ptr<Event>* new_event) 95 OVERRIDE { 96 NOTREACHED(); 97 return status_; 98 } 99 100 private: 101 EventRewriteStatus status_; 102 EventType type_; 103}; 104 105// This EventRewriter runs a simple state machine; it is used to test 106// EVENT_REWRITE_DISPATCH_ANOTHER. 107class TestStateMachineEventRewriter : public EventRewriter { 108 public: 109 TestStateMachineEventRewriter() : last_rewritten_event_(0), state_(0) {} 110 void AddRule(int from_state, EventType from_type, 111 int to_state, EventType to_type, EventRewriteStatus to_status) { 112 RewriteResult r = {to_state, to_type, to_status}; 113 rules_.insert(std::pair<RewriteCase, RewriteResult>( 114 RewriteCase(from_state, from_type), r)); 115 } 116 virtual EventRewriteStatus RewriteEvent(const Event& event, 117 scoped_ptr<Event>* rewritten_event) 118 OVERRIDE { 119 RewriteRules::iterator find = 120 rules_.find(RewriteCase(state_, event.type())); 121 if (find == rules_.end()) 122 return EVENT_REWRITE_CONTINUE; 123 if ((find->second.status == EVENT_REWRITE_REWRITTEN) || 124 (find->second.status == EVENT_REWRITE_DISPATCH_ANOTHER)) { 125 last_rewritten_event_ = new TestEvent(find->second.type); 126 rewritten_event->reset(last_rewritten_event_); 127 } else { 128 last_rewritten_event_ = 0; 129 } 130 state_ = find->second.state; 131 return find->second.status; 132 } 133 virtual EventRewriteStatus NextDispatchEvent(const Event& last_event, 134 scoped_ptr<Event>* new_event) 135 OVERRIDE { 136 EXPECT_TRUE(last_rewritten_event_); 137 const TestEvent* arg_last = static_cast<const TestEvent*>(&last_event); 138 EXPECT_EQ(last_rewritten_event_->unique_id(), arg_last->unique_id()); 139 const TestEvent* arg_new = static_cast<const TestEvent*>(new_event->get()); 140 EXPECT_FALSE(arg_new && arg_last->unique_id() == arg_new->unique_id()); 141 return RewriteEvent(last_event, new_event); 142 } 143 144 private: 145 typedef std::pair<int, EventType> RewriteCase; 146 struct RewriteResult { 147 int state; 148 EventType type; 149 EventRewriteStatus status; 150 }; 151 typedef std::map<RewriteCase, RewriteResult> RewriteRules; 152 RewriteRules rules_; 153 TestEvent* last_rewritten_event_; 154 int state_; 155}; 156 157} // namespace 158 159TEST(EventRewriterTest, EventRewriting) { 160 // TestEventRewriter r0 always rewrites events to ET_CANCEL_MODE; 161 // it is placed at the beginning of the chain and later removed, 162 // to verify that rewriter removal works. 163 TestConstantEventRewriter r0(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE); 164 165 // TestEventRewriter r1 always returns EVENT_REWRITE_CONTINUE; 166 // it is placed at the beginning of the chain to verify that a 167 // later rewriter sees the events. 168 TestConstantEventRewriter r1(EVENT_REWRITE_CONTINUE, ET_UNKNOWN); 169 170 // TestEventRewriter r2 has a state machine, primarily to test 171 // |EVENT_REWRITE_DISPATCH_ANOTHER|. 172 TestStateMachineEventRewriter r2; 173 174 // TestEventRewriter r3 always rewrites events to ET_CANCEL_MODE; 175 // it is placed at the end of the chain to verify that previously 176 // rewritten events are not passed further down the chain. 177 TestConstantEventRewriter r3(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE); 178 179 TestEventRewriteProcessor p; 180 TestEventRewriteSource s(&p); 181 s.AddEventRewriter(&r0); 182 s.AddEventRewriter(&r1); 183 s.AddEventRewriter(&r2); 184 185 // These events should be rewritten by r0 to ET_CANCEL_MODE. 186 p.AddExpectedEvent(ET_CANCEL_MODE); 187 s.Send(ET_MOUSE_DRAGGED); 188 p.AddExpectedEvent(ET_CANCEL_MODE); 189 s.Send(ET_MOUSE_PRESSED); 190 p.CheckAllReceived(); 191 192 // Remove r0, and verify that it's gone and that events make it through. 193 s.AddEventRewriter(&r3); 194 s.RemoveEventRewriter(&r0); 195 r2.AddRule(0, ET_SCROLL_FLING_START, 196 0, ET_SCROLL_FLING_CANCEL, EVENT_REWRITE_REWRITTEN); 197 p.AddExpectedEvent(ET_SCROLL_FLING_CANCEL); 198 s.Send(ET_SCROLL_FLING_START); 199 p.CheckAllReceived(); 200 s.RemoveEventRewriter(&r3); 201 202 // Verify EVENT_REWRITE_DISPATCH_ANOTHER using a state machine 203 // (that happens to be analogous to sticky keys). 204 r2.AddRule(0, ET_KEY_PRESSED, 205 1, ET_KEY_PRESSED, EVENT_REWRITE_CONTINUE); 206 r2.AddRule(1, ET_MOUSE_PRESSED, 207 0, ET_MOUSE_PRESSED, EVENT_REWRITE_CONTINUE); 208 r2.AddRule(1, ET_KEY_RELEASED, 209 2, ET_KEY_RELEASED, EVENT_REWRITE_DISCARD); 210 r2.AddRule(2, ET_MOUSE_RELEASED, 211 3, ET_MOUSE_RELEASED, EVENT_REWRITE_DISPATCH_ANOTHER); 212 r2.AddRule(3, ET_MOUSE_RELEASED, 213 0, ET_KEY_RELEASED, EVENT_REWRITE_REWRITTEN); 214 p.AddExpectedEvent(ET_KEY_PRESSED); 215 s.Send(ET_KEY_PRESSED); 216 s.Send(ET_KEY_RELEASED); 217 p.AddExpectedEvent(ET_MOUSE_PRESSED); 218 s.Send(ET_MOUSE_PRESSED); 219 220 // Removing rewriters r1 and r3 shouldn't affect r2. 221 s.RemoveEventRewriter(&r1); 222 s.RemoveEventRewriter(&r3); 223 224 // Continue with the state-based rewriting. 225 p.AddExpectedEvent(ET_MOUSE_RELEASED); 226 p.AddExpectedEvent(ET_KEY_RELEASED); 227 s.Send(ET_MOUSE_RELEASED); 228 p.CheckAllReceived(); 229} 230 231} // namespace ui 232