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