blob: 61557bcdbe010096ec42da9439679b978c0f2c6a [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// 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_++) {}
Dave Moorecc0e4f92015-03-10 15:23:04 -070025 ~TestEvent() override {}
James Robinson646469d2014-10-03 15:33:28 -070026 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() {}
Dave Moorecc0e4f92015-03-10 15:23:04 -070041 ~TestEventRewriteProcessor() override { CheckAllReceived(); }
James Robinson646469d2014-10-03 15:33:28 -070042
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:
Dave Moorecc0e4f92015-03-10 15:23:04 -070048 EventDispatchDetails OnEventFromSource(Event* event) override {
James Robinson646469d2014-10-03 15:33:28 -070049 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) {}
Dave Moorecc0e4f92015-03-10 15:23:04 -070065 EventProcessor* GetEventProcessor() override { return processor_; }
James Robinson646469d2014-10-03 15:33:28 -070066 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
Dave Moorecc0e4f92015-03-10 15:23:04 -070086 EventRewriteStatus RewriteEvent(const Event& event,
Craig Stoutf8b40b52015-08-13 11:48:01 -070087 scoped_ptr<Event>* rewritten_event) override {
James Robinson646469d2014-10-03 15:33:28 -070088 if (status_ == EVENT_REWRITE_REWRITTEN)
89 rewritten_event->reset(new TestEvent(type_));
90 return status_;
91 }
Dave Moorecc0e4f92015-03-10 15:23:04 -070092 EventRewriteStatus NextDispatchEvent(const Event& last_event,
93 scoped_ptr<Event>* new_event) override {
James Robinson646469d2014-10-03 15:33:28 -070094 NOTREACHED();
95 return status_;
96 }
97
98 private:
99 EventRewriteStatus status_;
100 EventType type_;
101};
102
103// This EventRewriter runs a simple state machine; it is used to test
104// EVENT_REWRITE_DISPATCH_ANOTHER.
105class TestStateMachineEventRewriter : public EventRewriter {
106 public:
107 TestStateMachineEventRewriter() : last_rewritten_event_(0), state_(0) {}
108 void AddRule(int from_state, EventType from_type,
109 int to_state, EventType to_type, EventRewriteStatus to_status) {
110 RewriteResult r = {to_state, to_type, to_status};
111 rules_.insert(std::pair<RewriteCase, RewriteResult>(
112 RewriteCase(from_state, from_type), r));
113 }
Dave Moorecc0e4f92015-03-10 15:23:04 -0700114 EventRewriteStatus RewriteEvent(const Event& event,
115 scoped_ptr<Event>* rewritten_event) override {
James Robinson646469d2014-10-03 15:33:28 -0700116 RewriteRules::iterator find =
117 rules_.find(RewriteCase(state_, event.type()));
118 if (find == rules_.end())
119 return EVENT_REWRITE_CONTINUE;
120 if ((find->second.status == EVENT_REWRITE_REWRITTEN) ||
121 (find->second.status == EVENT_REWRITE_DISPATCH_ANOTHER)) {
122 last_rewritten_event_ = new TestEvent(find->second.type);
123 rewritten_event->reset(last_rewritten_event_);
124 } else {
125 last_rewritten_event_ = 0;
126 }
127 state_ = find->second.state;
128 return find->second.status;
129 }
Dave Moorecc0e4f92015-03-10 15:23:04 -0700130 EventRewriteStatus NextDispatchEvent(const Event& last_event,
131 scoped_ptr<Event>* new_event) override {
James Robinson646469d2014-10-03 15:33:28 -0700132 EXPECT_TRUE(last_rewritten_event_);
133 const TestEvent* arg_last = static_cast<const TestEvent*>(&last_event);
134 EXPECT_EQ(last_rewritten_event_->unique_id(), arg_last->unique_id());
135 const TestEvent* arg_new = static_cast<const TestEvent*>(new_event->get());
136 EXPECT_FALSE(arg_new && arg_last->unique_id() == arg_new->unique_id());
137 return RewriteEvent(last_event, new_event);
138 }
139
140 private:
141 typedef std::pair<int, EventType> RewriteCase;
142 struct RewriteResult {
143 int state;
144 EventType type;
145 EventRewriteStatus status;
146 };
147 typedef std::map<RewriteCase, RewriteResult> RewriteRules;
148 RewriteRules rules_;
149 TestEvent* last_rewritten_event_;
150 int state_;
151};
152
153} // namespace
154
155TEST(EventRewriterTest, EventRewriting) {
156 // TestEventRewriter r0 always rewrites events to ET_CANCEL_MODE;
157 // it is placed at the beginning of the chain and later removed,
158 // to verify that rewriter removal works.
159 TestConstantEventRewriter r0(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
160
161 // TestEventRewriter r1 always returns EVENT_REWRITE_CONTINUE;
162 // it is placed at the beginning of the chain to verify that a
163 // later rewriter sees the events.
164 TestConstantEventRewriter r1(EVENT_REWRITE_CONTINUE, ET_UNKNOWN);
165
166 // TestEventRewriter r2 has a state machine, primarily to test
167 // |EVENT_REWRITE_DISPATCH_ANOTHER|.
168 TestStateMachineEventRewriter r2;
169
170 // TestEventRewriter r3 always rewrites events to ET_CANCEL_MODE;
171 // it is placed at the end of the chain to verify that previously
172 // rewritten events are not passed further down the chain.
173 TestConstantEventRewriter r3(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
174
175 TestEventRewriteProcessor p;
176 TestEventRewriteSource s(&p);
177 s.AddEventRewriter(&r0);
178 s.AddEventRewriter(&r1);
179 s.AddEventRewriter(&r2);
180
181 // These events should be rewritten by r0 to ET_CANCEL_MODE.
182 p.AddExpectedEvent(ET_CANCEL_MODE);
183 s.Send(ET_MOUSE_DRAGGED);
184 p.AddExpectedEvent(ET_CANCEL_MODE);
185 s.Send(ET_MOUSE_PRESSED);
186 p.CheckAllReceived();
187
188 // Remove r0, and verify that it's gone and that events make it through.
189 s.AddEventRewriter(&r3);
190 s.RemoveEventRewriter(&r0);
191 r2.AddRule(0, ET_SCROLL_FLING_START,
192 0, ET_SCROLL_FLING_CANCEL, EVENT_REWRITE_REWRITTEN);
193 p.AddExpectedEvent(ET_SCROLL_FLING_CANCEL);
194 s.Send(ET_SCROLL_FLING_START);
195 p.CheckAllReceived();
196 s.RemoveEventRewriter(&r3);
197
198 // Verify EVENT_REWRITE_DISPATCH_ANOTHER using a state machine
199 // (that happens to be analogous to sticky keys).
200 r2.AddRule(0, ET_KEY_PRESSED,
201 1, ET_KEY_PRESSED, EVENT_REWRITE_CONTINUE);
202 r2.AddRule(1, ET_MOUSE_PRESSED,
203 0, ET_MOUSE_PRESSED, EVENT_REWRITE_CONTINUE);
204 r2.AddRule(1, ET_KEY_RELEASED,
205 2, ET_KEY_RELEASED, EVENT_REWRITE_DISCARD);
206 r2.AddRule(2, ET_MOUSE_RELEASED,
207 3, ET_MOUSE_RELEASED, EVENT_REWRITE_DISPATCH_ANOTHER);
208 r2.AddRule(3, ET_MOUSE_RELEASED,
209 0, ET_KEY_RELEASED, EVENT_REWRITE_REWRITTEN);
210 p.AddExpectedEvent(ET_KEY_PRESSED);
211 s.Send(ET_KEY_PRESSED);
212 s.Send(ET_KEY_RELEASED);
213 p.AddExpectedEvent(ET_MOUSE_PRESSED);
214 s.Send(ET_MOUSE_PRESSED);
215
216 // Removing rewriters r1 and r3 shouldn't affect r2.
217 s.RemoveEventRewriter(&r1);
218 s.RemoveEventRewriter(&r3);
219
220 // Continue with the state-based rewriting.
221 p.AddExpectedEvent(ET_MOUSE_RELEASED);
222 p.AddExpectedEvent(ET_KEY_RELEASED);
223 s.Send(ET_MOUSE_RELEASED);
224 p.CheckAllReceived();
225}
226
227} // namespace ui