Implements TouchEventCheckTest for libinput haltests
authordyamy-lee <dyamy.lee@samsung.com>
Wed, 21 Apr 2021 08:01:49 +0000 (17:01 +0900)
committerduna.oh <duna.oh@samsung.com>
Fri, 27 Jan 2023 05:46:31 +0000 (14:46 +0900)
It's same way of checking MouseEventCheckTest.
For test, get lists of libinput devices and check validation of created touch event.
Only different thing with others is check it is mult touch support.
It supports multi touch, it generates libiput touch event and saves sequencely. For example, touch down, move, up.
It checkes devices capability which is touch, and checkes matching of events. If one of them checked successfully same events as created events, other touch devices can be skipped.

Change-Id: I0a60e675c14714c67debd0cfaac3c9ed80a1dc03

haltests/meson.build
haltests/test_hal_libinput.cpp
haltests/test_hal_libinput_eventgen.cpp
haltests/test_hal_libinput_eventgen.h
haltests/test_hal_libinput_info.cpp
haltests/test_hal_libinput_info.h
haltests/test_hal_libinput_mtdev_check.cpp [new file with mode: 0644]
haltests/test_hal_libinput_mtdev_check.h [new file with mode: 0644]

index a84da3d..2ebe3c6 100644 (file)
@@ -7,6 +7,7 @@ libinput_haltests_srcs = [
     'test_hal_libinput.cpp',
     'test_hal_libinput_info.cpp',
     'test_hal_libinput_eventgen.cpp',
+    'test_hal_libinput_mtdev_check.cpp',
 ]
 
 libinput_haltests_include_dirs = include_directories(
index 217220f..a043615 100644 (file)
@@ -60,5 +60,6 @@ TEST_F(LibInputHalTest, KeyboardEventCheckTest)
 
 TEST_F(LibInputHalTest, TouchEventCheckTest)
 {
-       EXPECT_TRUE(true);
+       EXPECT_TRUE(handle_libinput_add_event(li) != -1);
+       EXPECT_TRUE(validate_touch_event(li));
 }
index 17d3377..99c162e 100644 (file)
@@ -76,6 +76,36 @@ static void _key_gen(int keycode, int value)
        _write_event_to_device_node(EV_KEY, keycode, value);
 }
 
+static void _touch_gen_mt_slot(int value)
+{
+       _write_event_to_device_node(EV_ABS, ABS_MT_SLOT, value);
+}
+
+static void _touch_gen_mt_tracking_id(int value)
+{
+       _write_event_to_device_node(EV_ABS, ABS_MT_TRACKING_ID, value);
+}
+
+static void _touch_gen_mt_touch_major(int value)
+{
+       _write_event_to_device_node(EV_ABS, ABS_MT_TOUCH_MAJOR, value);
+}
+
+static void _touch_gen_mt_touch_minor(int value)
+{
+       _write_event_to_device_node(EV_ABS, ABS_MT_TOUCH_MINOR, value);
+}
+
+static void _touch_gen_mt_position_x(int value)
+{
+       _write_event_to_device_node(EV_ABS, ABS_MT_POSITION_X, value);
+}
+
+static void _touch_gen_mt_position_y(int value)
+{
+       _write_event_to_device_node(EV_ABS, ABS_MT_POSITION_Y, value);
+}
+
 static void _button_gen_down(int button)
 {
        if(button <3)
@@ -113,6 +143,39 @@ static void _key_gen_up(int key_code)
        _sync_gen();
 }
 
+static void _touch_gen_down(int idx, int x, int y)
+{
+#define MAX_TRACKING_ID 65535
+       static int tracking_id = 0;
+
+       _touch_gen_mt_slot(idx);
+       _touch_gen_mt_tracking_id(tracking_id);
+       tracking_id++;
+       if(tracking_id > MAX_TRACKING_ID)
+               tracking_id = 0;
+
+       _touch_gen_mt_touch_major(10);
+       _touch_gen_mt_touch_minor(5);
+       _touch_gen_mt_position_x(x);
+       _touch_gen_mt_position_y(y);
+       _sync_gen();
+}
+
+static void _touch_gen_move(int idx, int x, int y)
+{
+       _touch_gen_mt_slot(idx);
+       _touch_gen_mt_position_x(x);
+       _touch_gen_mt_position_y(y);
+       _sync_gen();
+}
+
+static void _touch_gen_up(int idx)
+{
+       _touch_gen_mt_slot(idx);
+       _touch_gen_mt_tracking_id(-1);
+       _sync_gen();
+}
+
 static void _input_mousegen(int button, int x, int y, int mouse_state)
 {
        switch(mouse_state) {
@@ -162,6 +225,28 @@ static void _input_keygen(int key_code, int key_state)
        }
 }
 
+static void _input_touchgen(int idx, int x, int y, int touch_state)
+{
+       switch(touch_state) {
+       case EVENT_STATE_PRESS:
+               _touch_gen_down(idx, x, y);
+               break;
+       case EVENT_STATE_RELEASE:
+               _touch_gen_up(idx);
+               break;
+       case EVENT_STATE_MOTION:
+               _touch_gen_move(idx, x, y);
+               break;
+       case EVENT_STATE_ALL:
+               _touch_gen_down(idx, x, y);
+               _touch_gen_move(idx, x, y);
+               _touch_gen_up(idx);
+               break;
+       default:
+               return;
+       }
+}
+
 int input_mouse_event_gen(int _fd, int button, int x, int y, int state)
 {
        if (_fd < 0) return -1;
@@ -179,3 +264,12 @@ int input_keyboard_event_gen(int _fd, int code, int state)
 
        return 0;
 }
+
+int input_touch_event_gen(int _fd, int idx, int x, int y, int state)
+{
+       if(_fd < 0) return -1;
+       fd = _fd;
+       _input_touchgen(idx, x, y, state);
+
+       return 0;
+}
index 0b0c37f..d1eac10 100644 (file)
@@ -37,6 +37,7 @@ typedef enum
 
 int input_mouse_event_gen(int _fd, int button, int x, int y, int state);
 int input_keyboard_event_gen(int _fd, int code, int state);
+int input_touch_event_gen(int _fd, int idx, int x, int y, int state);
 
 #ifdef __cplusplus
 }
index 35d74f7..70d45fe 100644 (file)
@@ -1,5 +1,6 @@
 #include "test_hal_libinput_info.h"
 #include "test_hal_libinput_eventgen.h"
+#include "test_hal_libinput_mtdev_check.h"
 #include <limits.h>
 #include <libevdev/libevdev.h>
 #include <libevdev/libevdev-uinput.h>
@@ -298,6 +299,69 @@ handle_pointer_axis_event(struct libinput_event *ev)
 static int
 handle_touch_event(struct libinput_event *ev)
 {
+       enum libinput_event_type etype = libinput_event_get_type(ev);
+       struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
+       const char *type;
+       double x, y;
+       double tx, ty;
+       int32_t slot, seat_slot;
+
+       switch(etype) {
+       case LIBINPUT_EVENT_TOUCH_DOWN:
+               type = "TOUCH_DOWN";
+               break;
+       case LIBINPUT_EVENT_TOUCH_UP:
+               type = "TOUCH_UP";
+               break;
+       case LIBINPUT_EVENT_TOUCH_MOTION:
+               type = "TOUCH_MOTION";
+               break;
+       case LIBINPUT_EVENT_TOUCH_CANCEL:
+               type = "TOUCH_CANCEL";
+               break;
+       case LIBINPUT_EVENT_TOUCH_FRAME:
+               type = "TOUCH_FRAME";
+               break;
+       default:
+               abort();
+       }
+
+       if (etype != LIBINPUT_EVENT_TOUCH_FRAME) {
+               slot = libinput_event_touch_get_slot(t);
+               seat_slot = libinput_event_touch_get_seat_slot(t);
+       }
+
+       switch (etype) {
+       case LIBINPUT_EVENT_TOUCH_FRAME:
+               LOG("type: %s\n", type);
+               break;
+       case LIBINPUT_EVENT_TOUCH_DOWN:
+       case LIBINPUT_EVENT_TOUCH_MOTION:
+               x = libinput_event_touch_get_x(t);
+               y = libinput_event_touch_get_y(t);
+               tx = libinput_event_touch_get_x_transformed(t, 100);
+               ty = libinput_event_touch_get_y_transformed(t, 100);
+               LOG("type: %s, slot: %d, seat_slot: %d, point: [%6.2f, %6.2f], transformed: [%6.2f, %6.2f]\n",
+                        type, slot, seat_slot, x, y, tx, ty);
+               LOG("type = %d, slot : %d, x = %d, y = %d, state = %d\n", queue_record_event[pop_idx].t.event_type, queue_record_event[pop_idx].t.idx, queue_record_event[pop_idx].t.x,
+                                       queue_record_event[pop_idx].t.y, queue_record_event[pop_idx].t.state);
+               EXPECT_EQ(queue_record_event[pop_idx].t.event_type, etype);
+               EXPECT_EQ(queue_record_event[pop_idx].t.idx, (int)slot);
+               EXPECT_EQ(queue_record_event[pop_idx].t.x, (int)x);
+               EXPECT_EQ(queue_record_event[pop_idx].t.y, (int)y);
+               break;
+       case LIBINPUT_EVENT_TOUCH_UP:
+       case LIBINPUT_EVENT_TOUCH_CANCEL:
+               LOG("type: %s, slot: %d, seat_slot: %d\n",
+                        type, slot, seat_slot);
+               LOG("type = %d, slot : %d,state = %d\n", queue_record_event[pop_idx].t.event_type, queue_record_event[pop_idx].t.idx,
+                                       queue_record_event[pop_idx].t.state);
+               EXPECT_EQ(queue_record_event[pop_idx].t.event_type, etype);
+               EXPECT_EQ(queue_record_event[pop_idx].t.idx, (int)slot);
+               break;
+       default:
+               abort();
+       }
        return 0;
 }
 
@@ -438,6 +502,76 @@ int create_keyboard_event(struct libinput *li, int idx)
        return 0;
 }
 
+int multi_touch_support(struct libinput *li, int idx)
+{
+       int fd = -1;
+
+       if(devices[idx].cap == LIBINPUT_DEVICE_CAP_TOUCH){
+               LOG("multi_touch_support\n");
+               fd = open(devices[idx].path, O_RDONLY | O_NONBLOCK);
+               if (fd < 0) {
+                       LOGE("ERROR: could not open device\n");
+                       return -1;
+               }
+               if (ioctl(fd, EVIOCGRAB, 1)) {
+                       LOGE("ERROR: could not grab the device\n");
+                       return -1;
+               }
+               if (check_device_mtprops(fd) < 0) {
+                       ioctl(fd, EVIOCGRAB, 0);
+                       close(fd);
+                       LOGE("ERROR: NO mt must props\n");
+                       return -1;
+               }
+               ioctl(fd, EVIOCGRAB, 0);
+               close(fd);
+       }
+       else
+               return -1;
+       return 0;
+}
+
+int create_touch_event(struct libinput *li, int idx)
+{
+       int fd = -1;
+       int n = 0;
+
+       struct record_event rc_e;
+       struct record_libinput_event_touch t[] = {
+               {LIBINPUT_EVENT_TOUCH_DOWN, 1, 100, 100, 1},
+               {LIBINPUT_EVENT_TOUCH_MOTION, 1, 120, 150, 2},
+               {LIBINPUT_EVENT_TOUCH_UP, 1, 120, 150, 0},
+       };
+
+       if(devices[idx].cap == LIBINPUT_DEVICE_CAP_TOUCH){
+               LOG("create_touch_event\n");
+               fd = open(devices[idx].path, O_RDWR);
+               if (fd < 0) {
+                       LOGE("ERROR: could not open device\n");
+                       return -1;
+               }
+
+               n = sizeof(t)/sizeof(struct record_libinput_event_touch);
+               rc_e.device = LIBINPUT_DEVICE_CAP_TOUCH;
+               for(int i=0; i<n; ++i)
+               {
+                       rc_e.t = t[i];
+
+                       if(input_touch_event_gen(fd, t[i].idx, t[i].x, t[i].y, t[i].state) < 0) {
+                               LOG("No device\n");
+                               continue;
+                       }
+                       queue_record_event[queue_idx++] = rc_e;
+               }
+
+               libinput_dispatch(li);
+               close(fd);
+       }
+       else
+               return -1;
+       return 0;
+}
+
 bool validate_mouse_event(struct libinput *li)
 {
        bool val = false;
@@ -491,3 +625,35 @@ bool validate_keyboard_event(struct libinput *li)
        }
        return val;
 }
+
+bool validate_touch_event(struct libinput *li)
+{
+       bool val = false;
+       bool checked = false;
+       int ret = 0;
+
+       for(int i=0; i< devices_cnt; ++i) {
+               if(devices[i].cap == LIBINPUT_DEVICE_CAP_TOUCH) {
+                       LOG("LIBINPUT_DEVICE_CAP_TOUCH, path = %s\n", devices[i].path);
+                       checked = true;
+                       queue_idx = 0;
+                       pop_idx = -1;
+                       if(multi_touch_support(li, i) < 0) {
+                               LOG("NO MULTI TOUCH SURPPORT. dont' have to test touch\n");
+                       }
+                       else{
+                               create_touch_event(li, i);
+                               ret = handle_libinput_event(li);
+                               if(queue_idx == (pop_idx+1) && !ret) {
+                                       val = true;
+                               }
+                       }
+               }
+               if(val) return true;
+       }
+       if(!val && !checked){
+               LOG("No Devices\n");
+               return true;
+       }
+       return val;
+}
index 86c8ca8..c37c156 100644 (file)
@@ -42,6 +42,7 @@ int handle_libinput_add_event(struct libinput *li);
 
 bool validate_mouse_event(struct libinput *li);
 bool validate_keyboard_event(struct libinput *li);
+bool validate_touch_event(struct libinput *li);
 
 struct record_device {
        enum libinput_device_capability cap;
diff --git a/haltests/test_hal_libinput_mtdev_check.cpp b/haltests/test_hal_libinput_mtdev_check.cpp
new file mode 100644 (file)
index 0000000..55133cf
--- /dev/null
@@ -0,0 +1,168 @@
+/*****************************************************************************
+ *
+ * mtdev - Multitouch Protocol Translation Library (MIT license)
+ *
+ * Copyright (C) 2010 Henrik Rydberg <rydberg@euromail.se>
+ * Copyright (C) 2010 Canonical Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ ****************************************************************************/
+
+#include <mtdev.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include "test_hal_libinput_mtdev_check.h"
+
+#ifndef input_event_sec
+#define input_event_sec time.tv_sec
+#define input_event_usec time.tv_usec
+#endif
+
+static int check_must_have(int code)
+{
+       int ret = -1;
+       switch (code)
+       {
+               case ABS_MT_SLOT:
+               case ABS_MT_TOUCH_MAJOR:
+               case ABS_MT_TOUCH_MINOR:
+               case ABS_MT_POSITION_X:
+               case ABS_MT_POSITION_Y:
+               case ABS_MT_TRACKING_ID:
+                       ret = 0;
+                       break;
+
+               case ABS_MT_WIDTH_MAJOR:
+               case ABS_MT_WIDTH_MINOR:
+               case ABS_MT_ORIENTATION:
+               case ABS_MT_TOOL_TYPE:
+               case ABS_MT_BLOB_ID:
+               case ABS_MT_PRESSURE:
+               case ABS_MT_DISTANCE:
+                       break;
+       }
+       return ret;
+}
+
+
+static const char* print_code(int code)
+{
+       const char * code_str = NULL;
+       switch (code)
+       {
+               case ABS_MT_SLOT:
+                       code_str = "ABS_MT_SLOT";
+                       break;
+               case ABS_MT_TOUCH_MAJOR:
+                       code_str = "ABS_MT_TOUCH_MAJOR";
+                       break;
+               case ABS_MT_TOUCH_MINOR:
+                       code_str = "ABS_MT_TOUCH_MINOR";
+                       break;
+               case ABS_MT_POSITION_X:
+                       code_str = "ABS_MT_POSITION_X";
+                       break;
+               case ABS_MT_POSITION_Y:
+                       code_str = "ABS_MT_POSITION_Y";
+                       break;
+               case ABS_MT_TRACKING_ID:
+                       code_str = "ABS_MT_TRACKING_ID";
+                       break;
+
+               case ABS_MT_WIDTH_MAJOR:
+                       code_str = "ABS_MT_WIDTH_MAJOR";
+                       break;
+               case ABS_MT_WIDTH_MINOR:
+                       code_str = "ABS_MT_WIDTH_MINOR";
+                       break;
+               case ABS_MT_ORIENTATION:
+                       code_str = "ABS_MT_ORIENTATION";
+                       break;
+               case ABS_MT_TOOL_TYPE:
+                       code_str = "ABS_MT_TOOL_TYPE";
+                       break;
+               case ABS_MT_BLOB_ID:
+                       code_str = "ABS_MT_BLOB_ID";
+                       break;
+               case ABS_MT_PRESSURE:
+                       code_str = "ABS_MT_PRESSURE";
+                       break;
+               case ABS_MT_DISTANCE:
+                       code_str = "ABS_MT_DISTANCE";
+                       break;
+       }
+       return code_str;
+}
+
+static int check_has_props(const struct mtdev *dev, int name)
+{
+       int ret = -1;
+       if(!check_must_have(name) && mtdev_has_mt_event(dev, name)) {
+               LOG("must have && it has : %s\n", print_code(name));
+               ret = 0;
+       }
+       else if (!check_must_have(name) && !mtdev_has_mt_event(dev, name)) {
+               LOGE("ERROR!! must have && it doesnt have : %s\n", print_code(name));
+               ret = -1;
+       }
+       else { // no must
+               LOG("don't have to : %s\n", print_code(name));
+               ret = 0;
+       }
+       return ret;
+}
+
+static int check_props(const struct mtdev *dev)
+{
+       LOG("supported mt events:\n");
+
+       if(check_has_props(dev, ABS_MT_SLOT) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_TOUCH_MAJOR) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_TOUCH_MINOR) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_WIDTH_MAJOR) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_WIDTH_MINOR) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_ORIENTATION) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_POSITION_X) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_POSITION_Y) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_TOOL_TYPE) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_BLOB_ID) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_TRACKING_ID) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_PRESSURE) < 0) return -1;
+       if(check_has_props(dev, ABS_MT_DISTANCE) < 0) return -1;
+
+       return 0;
+}
+
+int check_device_mtprops(int fd)
+{
+       int ret = -1;
+       struct mtdev dev;
+       ret = mtdev_open(&dev, fd);
+       if (ret) {
+               LOGE("ERROR! could not open device: %d\n", ret);
+               return -1;
+       }
+       ret = check_props(&dev);
+       mtdev_close(&dev);
+       return ret;
+}
diff --git a/haltests/test_hal_libinput_mtdev_check.h b/haltests/test_hal_libinput_mtdev_check.h
new file mode 100644 (file)
index 0000000..947889b
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __LIBINPUT_TESTS_MT_H__
+#define __LIBINPUT_TESTS_MT_H__
+
+#include <stdio.h>
+#include "test_hal_libinput_info.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/input.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+
+int check_device_mtprops(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LIBINPUT_TESTS_MT_H__
\ No newline at end of file