Index: ui/base/linux/touch_event_from_evdev_converter_unittest.cc |
diff --git a/ui/base/linux/touch_event_from_evdev_converter_unittest.cc b/ui/base/linux/touch_event_from_evdev_converter_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..89f9d0e7ec8b9c9fae809ed1c60b950bf2b1cdf3 |
--- /dev/null |
+++ b/ui/base/linux/touch_event_from_evdev_converter_unittest.cc |
@@ -0,0 +1,401 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <unistd.h> |
+#include <linux/input.h> |
+#include <errno.h> |
+#include <fcntl.h> |
+#include <unistd.h> |
+ |
+#include "base/memory/scoped_ptr.h" |
+#include "base/memory/scoped_vector.h" |
+#include "ui/base/linux/touch_event_from_evdev_converter.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "base/posix/eintr_wrapper.h" |
+#include "base/time.h" |
+ |
+#include "ui/base/events/event.h" |
+ |
+#include <vector> |
+ |
+namespace { |
+ |
+static int SetNonBlocking(int fd) { |
+ int flags = fcntl(fd, F_GETFL, 0); |
+ if (flags == -1) |
+ flags = 0; |
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK); |
+} |
+ |
+} // namespace |
+ |
+namespace ui { |
+ |
+class MockTouchEventFromEvdevConverter : public TouchEventFromEvdevConverter { |
+ public: |
+ MockTouchEventFromEvdevConverter(int a, int b); |
+ ~MockTouchEventFromEvdevConverter() { |
+ }; |
+ |
+ void ConfigureReadMock(struct input_event* queue, |
+ long read_this_many, |
+ long queue_index); |
+ |
+ unsigned size() { return dispatched_events_.size(); } |
+ TouchEvent* event(unsigned index) { return dispatched_events_[index]; } |
+ |
+ // Actually dispatch the event reader code. |
+ void ReadNow() { |
+ OnFileCanReadWithoutBlocking(read_pipe_); |
+ } |
+ |
+ private: |
+ virtual void DispatchEvent(TouchEvent* tev) OVERRIDE; |
+ |
+ int read_pipe_; |
+ int write_pipe_; |
+ |
+ ScopedVector<TouchEvent> dispatched_events_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MockTouchEventFromEvdevConverter); |
+}; |
+ |
+ |
+MockTouchEventFromEvdevConverter::MockTouchEventFromEvdevConverter(int a, int b) |
+ : TouchEventFromEvdevConverter(a, b) { |
+ pressure_min_ = 30; |
+ pressure_max_ = 60; |
+ |
+ int fds[2]; |
+ |
+ DCHECK(pipe(fds) >= 0) << "pipe() failed, errno: " << errno; |
+ DCHECK(SetNonBlocking(fds[0]) == 0) |
+ << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; |
+ DCHECK(SetNonBlocking(fds[1]) == 0) |
+ << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; |
+ read_pipe_ = fds[0]; |
+ write_pipe_ = fds[1]; |
+} |
+ |
+void MockTouchEventFromEvdevConverter::DispatchEvent(TouchEvent* tev) { |
+ dispatched_events_.push_back(tev); |
+} |
+ |
+void MockTouchEventFromEvdevConverter::ConfigureReadMock( |
+ struct input_event* queue, |
+ long read_this_many, |
+ long queue_index) { |
+ int nwrite = HANDLE_EINTR(write( |
+ write_pipe_, |
+ queue + queue_index, |
+ sizeof(struct input_event) * read_this_many)); |
+ DCHECK(nwrite == static_cast<int>( |
+ sizeof(struct input_event) * read_this_many)) |
+ << "write() failed, errno: " << errno; |
+} |
+ |
+} // namespace ui |
+ |
+// Test fixture. |
+class TouchEventFromEvdevConverterTest : public testing::Test { |
+ public: |
+ TouchEventFromEvdevConverterTest() { } |
+ |
+ // Overridden from testing::Test: |
+ virtual void SetUp() OVERRIDE { |
+ device_ = new ui::MockTouchEventFromEvdevConverter(-1, 2); |
+ } |
+ virtual void TearDown() OVERRIDE { |
+ delete device_; |
+ } |
+ |
+ ui::MockTouchEventFromEvdevConverter* device() { return device_; } |
+ |
+ private: |
+ ui::MockTouchEventFromEvdevConverter* device_; |
+ DISALLOW_COPY_AND_ASSIGN(TouchEventFromEvdevConverterTest); |
+}; |
+ |
+// TODO(rjkroege): Test for valid handling of time stamps. |
+TEST_F(TouchEventFromEvdevConverterTest, TouchDown) { |
+ ui::MockTouchEventFromEvdevConverter* dev = device(); |
+ |
+ struct input_event mock_kernel_queue[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684 }, |
+ { {0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3 }, |
+ { {0, 0}, EV_ABS, ABS_MT_PRESSURE, 45 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 42 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ |
+ dev->ConfigureReadMock(mock_kernel_queue, 1, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(0u, dev->size()); |
+ |
+ dev->ConfigureReadMock(mock_kernel_queue, 2, 1); |
+ dev->ReadNow(); |
+ EXPECT_EQ(0u, dev->size()); |
+ |
+ dev->ConfigureReadMock(mock_kernel_queue, 3, 3); |
+ dev->ReadNow(); |
+ EXPECT_EQ(1u, dev->size()); |
+ |
+ ui::TouchEvent* event = dev->event(0); |
+ EXPECT_FALSE(event == NULL); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); |
+ EXPECT_EQ(42, event->x()); |
+ EXPECT_EQ(51, event->y()); |
+ EXPECT_EQ(0, event->touch_id()); |
+ EXPECT_FLOAT_EQ(.5f, event->force()); |
+ EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); |
+} |
+ |
+TEST_F(TouchEventFromEvdevConverterTest, NoEvents) { |
+ ui::MockTouchEventFromEvdevConverter* dev = device(); |
+ dev->ConfigureReadMock(NULL, 0, 0); |
+ EXPECT_EQ(0u, dev->size()); |
+} |
+ |
+TEST_F(TouchEventFromEvdevConverterTest, TouchMove) { |
+ ui::MockTouchEventFromEvdevConverter* dev = device(); |
+ |
+ struct input_event mock_kernel_queue_press[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684 }, |
+ { {0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3 }, |
+ { {0, 0}, EV_ABS, ABS_MT_PRESSURE, 45 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 42 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ |
+ struct input_event mock_kernel_queue_move1[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_PRESSURE, 50 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 42 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_Y, 43 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ |
+ struct input_event mock_kernel_queue_move2[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_Y, 42 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ |
+ |
+ // Setup and discard a press. |
+ dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(1u, dev->size()); |
+ |
+ dev->ConfigureReadMock(mock_kernel_queue_move1, 4, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(2u, dev->size()); |
+ ui::TouchEvent* event = dev->event(1); |
+ EXPECT_FALSE(event == NULL); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); |
+ EXPECT_EQ(42, event->x()); |
+ EXPECT_EQ(43, event->y()); |
+ EXPECT_EQ(0, event->touch_id()); |
+ EXPECT_FLOAT_EQ(2.f / 3.f, event->force()); |
+ EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); |
+ |
+ dev->ConfigureReadMock(mock_kernel_queue_move2, 2, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(3u, dev->size()); |
+ event = dev->event(2); |
+ EXPECT_FALSE(event == NULL); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); |
+ EXPECT_EQ(42, event->x()); |
+ EXPECT_EQ(42, event->y()); |
+ EXPECT_EQ(0, event->touch_id()); |
+ EXPECT_FLOAT_EQ(2.f / 3.f, event->force()); |
+ EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); |
+} |
+ |
+TEST_F(TouchEventFromEvdevConverterTest, TouchRelease) { |
+ ui::MockTouchEventFromEvdevConverter* dev = device(); |
+ |
+ struct input_event mock_kernel_queue_press[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684 }, |
+ { {0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3 }, |
+ { {0, 0}, EV_ABS, ABS_MT_PRESSURE, 45 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 42 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ |
+ struct input_event mock_kernel_queue_release[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ |
+ |
+ // Setup and discard a press. |
+ dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(1u, dev->size()); |
+ ui::TouchEvent* event = dev->event(0); |
+ EXPECT_FALSE(event == NULL); |
+ |
+ dev->ConfigureReadMock(mock_kernel_queue_release, 2, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(2u, dev->size()); |
+ event = dev->event(1); |
+ EXPECT_FALSE(event == NULL); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); |
+ EXPECT_EQ(42, event->x()); |
+ EXPECT_EQ(51, event->y()); |
+ EXPECT_EQ(0, event->touch_id()); |
+ EXPECT_FLOAT_EQ(.5f, event->force()); |
+ EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); |
+} |
+ |
+ |
+ |
+ |
+ |
+TEST_F(TouchEventFromEvdevConverterTest, TwoFingerGesture) { |
+ ui::MockTouchEventFromEvdevConverter* dev = device(); |
+ |
+ ui::TouchEvent* ev0; |
+ ui::TouchEvent* ev1; |
+ |
+ struct input_event mock_kernel_queue_press0[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684 }, |
+ { {0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3 }, |
+ { {0, 0}, EV_ABS, ABS_MT_PRESSURE, 45 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 42 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_Y, 51 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ // Setup and discard a press. |
+ dev->ConfigureReadMock(mock_kernel_queue_press0, 6, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(1u, dev->size()); |
+ |
+ struct input_event mock_kernel_queue_move0[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 40 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ // Setup and discard a move. |
+ dev->ConfigureReadMock(mock_kernel_queue_move0, 2, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(2u, dev->size()); |
+ |
+ struct input_event mock_kernel_queue_move0press1[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 40 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 }, |
+ { {0, 0}, EV_ABS, ABS_MT_SLOT, 1 }, |
+ { {0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 686 }, |
+ { {0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3 }, |
+ { {0, 0}, EV_ABS, ABS_MT_PRESSURE, 45 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 101 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_Y, 102 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ // Move on 0, press on 1. |
+ dev->ConfigureReadMock(mock_kernel_queue_move0press1, 9, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(4u, dev->size()); |
+ ev0 = dev->event(2); |
+ ev1 = dev->event(3); |
+ |
+ // Move |
+ EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); |
+ EXPECT_EQ(40, ev0->x()); |
+ EXPECT_EQ(51, ev0->y()); |
+ EXPECT_EQ(0, ev0->touch_id()); |
+ EXPECT_FLOAT_EQ(.5f, ev0->force()); |
+ EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); |
+ |
+ // Press |
+ EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); |
+ EXPECT_EQ(101, ev1->x()); |
+ EXPECT_EQ(102, ev1->y()); |
+ EXPECT_EQ(1, ev1->touch_id()); |
+ EXPECT_FLOAT_EQ(.5f, ev1->force()); |
+ EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); |
+ |
+ // Stationary 0, Moves 1. |
+ struct input_event mock_kernel_queue_stationary0_move1[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 40 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ dev->ConfigureReadMock(mock_kernel_queue_stationary0_move1, 2, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(5u, dev->size()); |
+ ev1 = dev->event(4); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); |
+ EXPECT_EQ(40, ev1->x()); |
+ EXPECT_EQ(102, ev1->y()); |
+ EXPECT_EQ(1, ev1->touch_id()); |
+ |
+ EXPECT_FLOAT_EQ(.5f, ev1->force()); |
+ EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); |
+ |
+ // Move 0, stationary 1. |
+ struct input_event mock_kernel_queue_move0_stationary1[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_SLOT, 0 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 39 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ dev->ConfigureReadMock(mock_kernel_queue_move0_stationary1, 3, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(6u, dev->size()); |
+ ev0 = dev->event(5); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); |
+ EXPECT_EQ(39, ev0->x()); |
+ EXPECT_EQ(51, ev0->y()); |
+ EXPECT_EQ(0, ev0->touch_id()); |
+ EXPECT_FLOAT_EQ(.5f, ev0->force()); |
+ EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); |
+ |
+ // Release 0, move 1. |
+ struct input_event mock_kernel_queue_release0_move1[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1 }, |
+ { {0, 0}, EV_ABS, ABS_MT_SLOT, 1 }, |
+ { {0, 0}, EV_ABS, ABS_MT_POSITION_X, 38 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 } }; |
+ dev->ConfigureReadMock(mock_kernel_queue_release0_move1, 4, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(8u, dev->size()); |
+ ev0 = dev->event(6); |
+ ev1 = dev->event(7); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); |
+ EXPECT_EQ(39, ev0->x()); |
+ EXPECT_EQ(51, ev0->y()); |
+ EXPECT_EQ(0, ev0->touch_id()); |
+ EXPECT_FLOAT_EQ(.5f, ev0->force()); |
+ EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); |
+ EXPECT_EQ(38, ev1->x()); |
+ EXPECT_EQ(102, ev1->y()); |
+ EXPECT_EQ(1, ev1->touch_id()); |
+ EXPECT_FLOAT_EQ(.5f, ev1->force()); |
+ EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); |
+ |
+ // Release 1. |
+ struct input_event mock_kernel_queue_release1[] = { |
+ { {0, 0}, EV_ABS, ABS_MT_TRACKING_ID, -1 }, |
+ { {0, 0}, EV_SYN, SYN_REPORT, 0 },}; |
+ dev->ConfigureReadMock(mock_kernel_queue_release1, 2, 0); |
+ dev->ReadNow(); |
+ EXPECT_EQ(9u, dev->size()); |
+ ev1 = dev->event(8); |
+ |
+ EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1->type()); |
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); |
+ EXPECT_EQ(38, ev1->x()); |
+ EXPECT_EQ(102, ev1->y()); |
+ EXPECT_EQ(1, ev1->touch_id()); |
+ EXPECT_FLOAT_EQ(.5f, ev1->force()); |
+ EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); |
+} |