All of lore.kernel.org
 help / color / mirror / Atom feed
* [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket
@ 2019-08-26 14:01 Cyril Hrubis
  2019-08-26 14:01 ` [LTP] [PATCH v3 1/5] lib/tst_device: Export more functions Cyril Hrubis
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Cyril Hrubis @ 2019-08-26 14:01 UTC (permalink / raw)
  To: ltp

This patchset adds three basic test for uevent netlink socket.

v3:

Fixed all problems pointed out by Clemens.

v2:

Finished the input event test, now we match all events.

*** BLURB HERE ***

Cyril Hrubis (5):
  lib/tst_device: Export more functions.
  kernel/uevent: Add uevent01
  kernel/uevent: Add uevent02
  libs/libltpuinput: Add uinput library.
  kernel/uevent: Add uevent03

 include/tst_device.h                |   7 +
 include/tst_uinput.h                |  48 ++++++
 lib/tst_device.c                    |   8 +-
 libs/libltpuinput/Makefile          |  12 ++
 libs/libltpuinput/tst_uinput.c      | 143 ++++++++++++++++
 runtest/uevent                      |   3 +
 scenario_groups/default             |   1 +
 testcases/kernel/uevents/.gitignore |   3 +
 testcases/kernel/uevents/Makefile   |  10 ++
 testcases/kernel/uevents/uevent.h   | 176 ++++++++++++++++++++
 testcases/kernel/uevents/uevent01.c |  98 +++++++++++
 testcases/kernel/uevents/uevent02.c | 143 ++++++++++++++++
 testcases/kernel/uevents/uevent03.c | 248 ++++++++++++++++++++++++++++
 13 files changed, 896 insertions(+), 4 deletions(-)
 create mode 100644 include/tst_uinput.h
 create mode 100644 libs/libltpuinput/Makefile
 create mode 100644 libs/libltpuinput/tst_uinput.c
 create mode 100644 runtest/uevent
 create mode 100644 testcases/kernel/uevents/.gitignore
 create mode 100644 testcases/kernel/uevents/Makefile
 create mode 100644 testcases/kernel/uevents/uevent.h
 create mode 100644 testcases/kernel/uevents/uevent01.c
 create mode 100644 testcases/kernel/uevents/uevent02.c
 create mode 100644 testcases/kernel/uevents/uevent03.c

-- 
2.21.0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 1/5] lib/tst_device: Export more functions.
  2019-08-26 14:01 [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Cyril Hrubis
@ 2019-08-26 14:01 ` Cyril Hrubis
  2019-08-26 15:57   ` Clemens Famulla-Conrad
  2019-08-26 14:01 ` [LTP] [PATCH v3 2/5] kernel/uevent: Add uevent01 Cyril Hrubis
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Cyril Hrubis @ 2019-08-26 14:01 UTC (permalink / raw)
  To: ltp

Export tst_attach_device() and tst_deteach_device() which will be later
on used by a kernel netlink uevent tests.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
Reviewed-by: Clemens Famulla-Conrad <cfamullaconrad@suse.de>
---
 include/tst_device.h | 7 +++++++
 lib/tst_device.c     | 8 ++++----
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/include/tst_device.h b/include/tst_device.h
index f0ddc3e93..c6e7b45b1 100644
--- a/include/tst_device.h
+++ b/include/tst_device.h
@@ -50,6 +50,13 @@ int tst_clear_device(const char *dev);
  *
  */
 int tst_find_free_loopdev(const char *path, size_t path_len);
+
+
+int tst_attach_device(const char *dev_path, const char *file_path);
+
+
+int tst_detach_device(const char *dev_path);
+
 /*
  * Reads test block device stat file and returns the bytes written since the
  * last call of this function.
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 22abdef46..10f71901d 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -139,7 +139,7 @@ int tst_find_free_loopdev(char *path, size_t path_len)
 	return -1;
 }
 
-static int attach_device(const char *dev, const char *file)
+int tst_attach_device(const char *dev, const char *file)
 {
 	int dev_fd, file_fd;
 	struct loop_info loopinfo;
@@ -185,7 +185,7 @@ static int attach_device(const char *dev, const char *file)
 	return 0;
 }
 
-static int detach_device(const char *dev)
+int tst_detach_device(const char *dev)
 {
 	int dev_fd, ret, i;
 
@@ -284,7 +284,7 @@ const char *tst_acquire_device__(unsigned int size)
 	if (tst_find_free_loopdev(dev_path, sizeof(dev_path)) == -1)
 		return NULL;
 
-	if (attach_device(dev_path, DEV_FILE))
+	if (tst_attach_device(dev_path, DEV_FILE))
 		return NULL;
 
 	device_acquired = 1;
@@ -329,7 +329,7 @@ int tst_release_device(const char *dev)
 	 *
 	 * The file image is deleted in tst_rmdir();
 	 */
-	ret = detach_device(dev);
+	ret = tst_detach_device(dev);
 
 	device_acquired = 0;
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 2/5] kernel/uevent: Add uevent01
  2019-08-26 14:01 [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Cyril Hrubis
  2019-08-26 14:01 ` [LTP] [PATCH v3 1/5] lib/tst_device: Export more functions Cyril Hrubis
@ 2019-08-26 14:01 ` Cyril Hrubis
  2019-08-26 15:57   ` Clemens Famulla-Conrad
  2019-08-26 14:01 ` [LTP] [PATCH v3 3/5] kernel/uevent: Add uevent02 Cyril Hrubis
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Cyril Hrubis @ 2019-08-26 14:01 UTC (permalink / raw)
  To: ltp

Simple test that attached and detaches a file to a loop device and
checks that kernel broadcasts correct events to the kernel uevent
broadcast group.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 runtest/uevent                      |   1 +
 scenario_groups/default             |   1 +
 testcases/kernel/uevents/.gitignore |   1 +
 testcases/kernel/uevents/Makefile   |   6 +
 testcases/kernel/uevents/uevent.h   | 176 ++++++++++++++++++++++++++++
 testcases/kernel/uevents/uevent01.c |  98 ++++++++++++++++
 6 files changed, 283 insertions(+)
 create mode 100644 runtest/uevent
 create mode 100644 testcases/kernel/uevents/.gitignore
 create mode 100644 testcases/kernel/uevents/Makefile
 create mode 100644 testcases/kernel/uevents/uevent.h
 create mode 100644 testcases/kernel/uevents/uevent01.c

diff --git a/runtest/uevent b/runtest/uevent
new file mode 100644
index 000000000..e9cdf26b8
--- /dev/null
+++ b/runtest/uevent
@@ -0,0 +1 @@
+uevent01 uevent01
diff --git a/scenario_groups/default b/scenario_groups/default
index 093f5f706..62ae0759d 100644
--- a/scenario_groups/default
+++ b/scenario_groups/default
@@ -29,3 +29,4 @@ input
 cve
 crypto
 kernel_misc
+uevent
diff --git a/testcases/kernel/uevents/.gitignore b/testcases/kernel/uevents/.gitignore
new file mode 100644
index 000000000..53d0b546a
--- /dev/null
+++ b/testcases/kernel/uevents/.gitignore
@@ -0,0 +1 @@
+uevent01
diff --git a/testcases/kernel/uevents/Makefile b/testcases/kernel/uevents/Makefile
new file mode 100644
index 000000000..cba769739
--- /dev/null
+++ b/testcases/kernel/uevents/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+top_srcdir			?= ../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/uevents/uevent.h b/testcases/kernel/uevents/uevent.h
new file mode 100644
index 000000000..908e150f0
--- /dev/null
+++ b/testcases/kernel/uevents/uevent.h
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+#ifndef UEVENT_H__
+#define UEVENT_H__
+
+#include "tst_netlink.h"
+
+/*
+ * There are two broadcast groups defined for the NETLINK_KOBJECT_UEVENT. The
+ * primary consument of the KERNEL group is udev which handles the hotplug
+ * events and then, once udev does it's magic the events are rebroadcasted to
+ * the UDEV group which is consumed by various daemons in the userspace.
+ */
+enum monitor_netlink_group {
+	MONITOR_GROUP_NONE,
+	MONITOR_GROUP_KERNEL,
+	MONITOR_GROUP_UDEV,
+};
+
+/*
+ * The messages received from the NETLINK_KOBJECT_UEVENT socket are stored as a
+ * sequence of a null-terminated strings. First in the buffer is a summary of a
+ * action i.e. "$ACTION@$DEVPATH" which is then followed by a bunch of
+ * key-value pairs.
+ *
+ * For example attaching a file to loopback device generates event:
+ *
+ * "change@/devices/virtual/block/loop0\0
+ *  ACTION=change\0
+ *  DEVPATH=/devices/virtual/block/loop0\0
+ *  SUBSYSTEM=block\0
+ *  MAJOR=7\0
+ *  MINOR=0\0
+ *  DEVNAME=loop0\0
+ *  DEVTYPE=disk\0
+ *  SEQNUM=2677\0"
+ */
+
+/*
+ * Prints uevent.
+ */
+static inline void print_uevent(const char *event, int len)
+{
+	int consumed = 0;
+
+	tst_res(TINFO, "Got uevent:");
+
+	while (consumed < len) {
+		tst_res(TINFO, "%s", event);
+		int l = strlen(event) + 1;
+		consumed += l;
+		event += l;
+	}
+}
+
+/*
+ * Uevents read from the socket are matched against this description.
+ *
+ * The msg is the overall action description e.g.
+ * "add@/class/input/input4/mouse1" which has to be matched exactly before we
+ * event attempt to check the key-value pairs stored in the values array. The
+ * event is considered to match if all key-value pairs in the values has been
+ * found in the received event.
+ */
+struct uevent_desc {
+	const char *msg;
+	int value_cnt;
+	const char **values;
+};
+
+static inline int uevent_match(const char *event, int len,
+                               const struct uevent_desc *uevent)
+{
+	int consumed = 0;
+	int val_matches = 0;
+
+	if (memcmp(event, uevent->msg, strlen(uevent->msg)))
+		return 0;
+
+	int l = strlen(event) + 1;
+
+	consumed += l;
+	event += l;
+
+	while (consumed < len) {
+		int i;
+		for (i = 0; i < uevent->value_cnt; i++) {
+			if (!strcmp(event, uevent->values[i])) {
+				val_matches++;
+				break;
+			}
+		}
+
+		l = strlen(event) + 1;
+		consumed += l;
+		event += l;
+	}
+
+	return val_matches == uevent->value_cnt;
+}
+
+static inline int open_uevent_netlink(void)
+{
+	int fd;
+	struct sockaddr_nl nl_addr = {
+		.nl_family = AF_NETLINK,
+		.nl_groups = MONITOR_GROUP_KERNEL,
+	};
+
+	fd = SAFE_SOCKET(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
+
+	SAFE_BIND(fd, (struct sockaddr *)&nl_addr, sizeof(nl_addr));
+
+	return fd;
+}
+
+/*
+ * Reads events from uevent netlink socket until all expected events passed in
+ * the uevent array are matched.
+ */
+static inline void wait_for_uevents(int fd, const struct uevent_desc *const uevents[])
+{
+	int i = 0;
+
+	while (1) {
+		int len;
+		char buf[4096];
+
+		len = recv(fd, &buf, sizeof(buf), 0);
+
+		if (len == 0)
+			continue;
+
+		print_uevent(buf, len);
+
+		if (uevent_match(buf, len, uevents[i])) {
+			tst_res(TPASS, "Got expected UEVENT");
+			if (!uevents[++i]) {
+				close(fd);
+				return;
+			}
+		}
+	}
+}
+
+/*
+ * Waits 5 seconds for a child to exit, kills the child after a timeout.
+ */
+static inline void wait_for_pid(int pid)
+{
+	int status, ret;
+	int retries = 5000;
+
+	do {
+		ret = waitpid(pid, &status, WNOHANG);
+		usleep(1000);
+	} while (ret == 0 && retries--);
+
+	if (ret == pid) {
+		if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+			return;
+
+		tst_res(TFAIL, "Child exitted with %s", tst_strstatus(status));
+	}
+
+	SAFE_KILL(pid, SIGKILL);
+
+	SAFE_WAITPID(pid, NULL, 0);
+
+	tst_res(TFAIL, "Did not get all expected UEVENTS");
+}
+
+#endif /* UEVENT_H__ */
diff --git a/testcases/kernel/uevents/uevent01.c b/testcases/kernel/uevents/uevent01.c
new file mode 100644
index 000000000..0dd1344a7
--- /dev/null
+++ b/testcases/kernel/uevents/uevent01.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*
+ * Very simple uevent netlink socket test.
+ *
+ * We fork a child that listens for a kernel events while parents attaches and
+ * detaches a loop device which should produce two change events.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include "tst_test.h"
+
+#include "uevent.h"
+
+static void generate_device_events(const char *dev_path)
+{
+	tst_fill_file("loop.img", 0, 1024, 1024);
+
+	tst_res(TINFO, "Attaching device %s", dev_path);
+	tst_attach_device(dev_path, "loop.img");
+	tst_res(TINFO, "Detaching device %s", dev_path);
+	tst_detach_device(dev_path);
+}
+
+static void verify_uevent(void)
+{
+	int pid, fd, dev_num;
+	char dev_path[1024];
+	char ev_msg[1024];
+	char ev_dev_path[1024];
+	char ev_dev_minor[128];
+	char ev_dev_name[128];
+
+	struct uevent_desc desc = {
+		.msg = ev_msg,
+		.value_cnt = 7,
+		.values = (const char*[]) {
+			"ACTION=change",
+			ev_dev_path,
+			"SUBSYSTEM=block",
+			"MAJOR=7",
+			ev_dev_minor,
+			ev_dev_name,
+			"DEVTYPE=disk",
+		}
+	};
+
+	dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path));
+
+	if (dev_num < 0)
+		tst_brk(TBROK, "Failed to find free loop device");
+
+	snprintf(ev_msg, sizeof(ev_msg),
+	         "change@/devices/virtual/block/loop%i", dev_num);
+
+	snprintf(ev_dev_path, sizeof(ev_dev_path),
+	         "DEVPATH=/devices/virtual/block/loop%i", dev_num);
+
+	snprintf(ev_dev_minor, sizeof(ev_dev_minor), "MINOR=%i", dev_num);
+	snprintf(ev_dev_name, sizeof(ev_dev_name), "DEVNAME=loop%i", dev_num);
+
+	const struct uevent_desc *const uevents[] = {
+		&desc,
+		&desc,
+		NULL
+	};
+
+	pid = SAFE_FORK();
+	if (!pid) {
+		fd = open_uevent_netlink();
+		TST_CHECKPOINT_WAKE(0);
+		wait_for_uevents(fd, uevents);
+		exit(0);
+	}
+
+	TST_CHECKPOINT_WAIT(0);
+
+	generate_device_events(dev_path);
+
+	wait_for_pid(pid);
+}
+
+static struct tst_test test = {
+	.test_all = verify_uevent,
+	.forks_child = 1,
+	.needs_tmpdir = 1,
+	.needs_checkpoints = 1,
+	.needs_drivers = (const char *const []) {
+		"loop",
+		NULL
+	},
+	.needs_root = 1
+};
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 3/5] kernel/uevent: Add uevent02
  2019-08-26 14:01 [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Cyril Hrubis
  2019-08-26 14:01 ` [LTP] [PATCH v3 1/5] lib/tst_device: Export more functions Cyril Hrubis
  2019-08-26 14:01 ` [LTP] [PATCH v3 2/5] kernel/uevent: Add uevent01 Cyril Hrubis
@ 2019-08-26 14:01 ` Cyril Hrubis
  2019-08-26 15:55   ` Clemens Famulla-Conrad
  2019-08-26 14:01 ` [LTP] [PATCH v3 4/5] libs/libltpuinput: Add uinput library Cyril Hrubis
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Cyril Hrubis @ 2019-08-26 14:01 UTC (permalink / raw)
  To: ltp

Similar to uevent01 but we create and remove a tun network card instead.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 runtest/uevent                      |   1 +
 testcases/kernel/uevents/.gitignore |   1 +
 testcases/kernel/uevents/uevent02.c | 143 ++++++++++++++++++++++++++++
 3 files changed, 145 insertions(+)
 create mode 100644 testcases/kernel/uevents/uevent02.c

diff --git a/runtest/uevent b/runtest/uevent
index e9cdf26b8..30b1114a4 100644
--- a/runtest/uevent
+++ b/runtest/uevent
@@ -1 +1,2 @@
 uevent01 uevent01
+uevent02 uevent02
diff --git a/testcases/kernel/uevents/.gitignore b/testcases/kernel/uevents/.gitignore
index 53d0b546a..0afc95534 100644
--- a/testcases/kernel/uevents/.gitignore
+++ b/testcases/kernel/uevents/.gitignore
@@ -1 +1,2 @@
 uevent01
+uevent02
diff --git a/testcases/kernel/uevents/uevent02.c b/testcases/kernel/uevents/uevent02.c
new file mode 100644
index 000000000..b94748c51
--- /dev/null
+++ b/testcases/kernel/uevents/uevent02.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*
+ * Very simple uevent netlink socket test.
+ *
+ * We fork a child that listens for a kernel events while parents creates and
+ * removes a tun network device which should produce two several add and remove
+ * events.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#include "tst_test.h"
+
+#include "uevent.h"
+
+#define TUN_PATH "/dev/net/tun"
+
+static void generate_tun_uevents(void)
+{
+	int fd = SAFE_OPEN(TUN_PATH, O_RDWR);
+
+	struct ifreq ifr = {
+		.ifr_flags = IFF_TUN,
+		.ifr_name = "ltp-tun0",
+	};
+
+	SAFE_IOCTL(fd, TUNSETIFF, (void*)&ifr);
+
+	SAFE_IOCTL(fd, TUNSETPERSIST, 0);
+
+	SAFE_CLOSE(fd);
+}
+
+static void verify_uevent(void)
+{
+	int pid, fd;
+
+	struct uevent_desc add = {
+		.msg = "add@/devices/virtual/net/ltp-tun0",
+		.value_cnt = 4,
+		.values = (const char*[]) {
+			"ACTION=add",
+			"DEVPATH=/devices/virtual/net/ltp-tun0",
+			"SUBSYSTEM=net",
+			"INTERFACE=ltp-tun0",
+		}
+	};
+
+	struct uevent_desc add_rx = {
+		.msg = "add@/devices/virtual/net/ltp-tun0/queues/rx-0",
+		.value_cnt = 3,
+		.values = (const char*[]) {
+			"ACTION=add",
+			"DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0",
+			"SUBSYSTEM=queues",
+		}
+	};
+
+	struct uevent_desc add_tx = {
+		.msg = "add@/devices/virtual/net/ltp-tun0/queues/tx-0",
+		.value_cnt = 3,
+		.values = (const char*[]) {
+			"ACTION=add",
+			"DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0",
+			"SUBSYSTEM=queues",
+		}
+	};
+
+	struct uevent_desc rem_rx = {
+		.msg = "remove@/devices/virtual/net/ltp-tun0/queues/rx-0",
+		.value_cnt = 3,
+		.values = (const char*[]) {
+			"ACTION=remove",
+			"DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0",
+			"SUBSYSTEM=queues",
+		}
+	};
+
+	struct uevent_desc rem_tx = {
+		.msg = "remove@/devices/virtual/net/ltp-tun0/queues/tx-0",
+		.value_cnt = 3,
+		.values = (const char*[]) {
+			"ACTION=remove",
+			"DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0",
+			"SUBSYSTEM=queues",
+		}
+	};
+
+	struct uevent_desc rem = {
+		.msg = "remove@/devices/virtual/net/ltp-tun0",
+		.value_cnt = 4,
+		.values = (const char*[]) {
+			"ACTION=remove",
+			"DEVPATH=/devices/virtual/net/ltp-tun0",
+			"SUBSYSTEM=net",
+			"INTERFACE=ltp-tun0",
+		}
+	};
+
+	const struct uevent_desc *const uevents[] = {
+		&add,
+		&add_rx,
+		&add_tx,
+		&rem_rx,
+		&rem_tx,
+		&rem,
+		NULL
+	};
+
+	pid = SAFE_FORK();
+	if (!pid) {
+		fd = open_uevent_netlink();
+		TST_CHECKPOINT_WAKE(0);
+		wait_for_uevents(fd, uevents);
+		exit(0);
+	}
+
+	TST_CHECKPOINT_WAIT(0);
+
+	generate_tun_uevents();
+
+	wait_for_pid(pid);
+}
+
+static struct tst_test test = {
+	.test_all = verify_uevent,
+	.forks_child = 1,
+	.needs_tmpdir = 1,
+	.needs_checkpoints = 1,
+	.needs_drivers = (const char *const []) {
+		"tun",
+		NULL
+	},
+	.needs_root = 1
+};
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 4/5] libs/libltpuinput: Add uinput library.
  2019-08-26 14:01 [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Cyril Hrubis
                   ` (2 preceding siblings ...)
  2019-08-26 14:01 ` [LTP] [PATCH v3 3/5] kernel/uevent: Add uevent02 Cyril Hrubis
@ 2019-08-26 14:01 ` Cyril Hrubis
  2019-08-26 15:55   ` Clemens Famulla-Conrad
  2019-08-26 14:01 ` [LTP] [PATCH v3 5/5] kernel/uevent: Add uevent03 Cyril Hrubis
  2019-08-26 15:59 ` [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Clemens Famulla-Conrad
  5 siblings, 1 reply; 13+ messages in thread
From: Cyril Hrubis @ 2019-08-26 14:01 UTC (permalink / raw)
  To: ltp

I to be used in the uevent03 test.

Also I will convert the uinput testcases to new library and make use of
this library as well.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 include/tst_uinput.h           |  48 +++++++++++
 libs/libltpuinput/Makefile     |  12 +++
 libs/libltpuinput/tst_uinput.c | 143 +++++++++++++++++++++++++++++++++
 3 files changed, 203 insertions(+)
 create mode 100644 include/tst_uinput.h
 create mode 100644 libs/libltpuinput/Makefile
 create mode 100644 libs/libltpuinput/tst_uinput.c

diff --git a/include/tst_uinput.h b/include/tst_uinput.h
new file mode 100644
index 000000000..dddbd9921
--- /dev/null
+++ b/include/tst_uinput.h
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+#ifndef TST_UINPUT_H__
+#define TST_UINPUT_H__
+
+/**
+ * Tries to open the uinput device.
+ *
+ * Returns file descriptor on success, -1 on failure.
+ */
+int open_uinput(void);
+
+/**
+ * Creates virtual input device.
+ *
+ * @fd File descriptor returned by open_uinput().
+ */
+void create_input_device(int fd);
+
+/**
+ * Parses /proc/bus/input/devices and returns the handlers strings for our
+ * virtual device, which is list of input devices that receive events from the
+ * device separated by whitestpaces.
+ *
+ * Returns newly allocated string, list of handlers separated by whitespaces,
+ * or NULL in a case of failure.
+ */
+char *get_input_handlers(void);
+
+/**
+ * Sets up the virtual device to appear as a mouse, this must be called before
+ * the call to create_input_device().
+ *
+ * @fd File descriptor as returned by open_uinput().
+ */
+void setup_mouse_events(int fd);
+
+/**
+ * Destroys virtual input device.
+ *
+ * @fd File descriptor returned by open_uinput().
+ */
+void destroy_input_device(int fd);
+
+#endif	/* TST_UINPUT_H__ */
diff --git a/libs/libltpuinput/Makefile b/libs/libltpuinput/Makefile
new file mode 100644
index 000000000..dd2a6c096
--- /dev/null
+++ b/libs/libltpuinput/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) Cyril Hrubis <chrubis@suse.cz>
+
+top_srcdir		?= ../..
+
+include $(top_srcdir)/include/mk/env_pre.mk
+
+LIB			:= libltpuinput.a
+
+include $(top_srcdir)/include/mk/lib.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/libs/libltpuinput/tst_uinput.c b/libs/libltpuinput/tst_uinput.c
new file mode 100644
index 000000000..4b22fef2a
--- /dev/null
+++ b/libs/libltpuinput/tst_uinput.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com>
+ * Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+#include <linux/input.h>
+#include <linux/uinput.h>
+#include <stdio.h>
+#include <string.h>
+
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+
+#include "tst_uinput.h"
+
+#define VIRTUAL_DEVICE "virtual-device-ltp"
+
+static const char *uinput_paths[] = {
+	"/dev/input/uinput",
+	"/dev/uinput",
+};
+
+int open_uinput(void)
+{
+	unsigned int i;
+	int fd;
+
+	for (i = 0; i < ARRAY_SIZE(uinput_paths); i++) {
+		fd = open(uinput_paths[i], O_WRONLY | O_NONBLOCK);
+
+		if (fd > 0) {
+			tst_res(TINFO, "Found uinput dev at %s", uinput_paths[i]);
+			return fd;
+		}
+
+		if (fd < 0 && errno != ENOENT) {
+			tst_brk(TBROK | TERRNO, "open(%s)", uinput_paths[i]);
+		}
+	}
+
+	return -1;
+}
+
+#define HANDLERS_PREFIX "Handlers="
+
+static char *parse_handlers(char *line)
+{
+	char *handlers;
+
+	handlers = strstr(line, HANDLERS_PREFIX) + sizeof(HANDLERS_PREFIX) - 1;
+
+	handlers[strlen(handlers) - 1] = 0;
+
+	return strdup(handlers);
+}
+
+char *get_input_handlers(void)
+{
+	FILE *file;
+	char line[1024];
+	int flag = 0;
+
+	file = fopen("/proc/bus/input/devices", "r");
+	if (!file)
+		return NULL;
+
+	while (fgets(line, sizeof(line), file)) {
+		if (strstr(line, "N: Name=\""VIRTUAL_DEVICE"\""))
+			flag = 1;
+
+		if (flag) {
+			if (line[0] == 'H')
+				return parse_handlers(line);
+
+			if (line[0] == '\n')
+				flag = 0;
+		}
+	}
+
+	fclose(file);
+	return NULL;
+}
+
+static int check_device(void)
+{
+	FILE *file;
+	char line[256];
+
+	file = fopen("/proc/bus/input/devices", "r");
+	if (!file)
+		return 0;
+
+	while (fgets(line, sizeof(line), file)) {
+		if (strstr(line, "Name=\""VIRTUAL_DEVICE"\""))
+			return 1;
+	}
+
+	fclose(file);
+
+	return 0;
+}
+
+void setup_mouse_events(int fd)
+{
+	SAFE_IOCTL(fd, UI_SET_EVBIT, EV_KEY);
+	SAFE_IOCTL(fd, UI_SET_KEYBIT, BTN_LEFT);
+	SAFE_IOCTL(fd, UI_SET_EVBIT, EV_REL);
+	SAFE_IOCTL(fd, UI_SET_RELBIT, REL_X);
+	SAFE_IOCTL(fd, UI_SET_RELBIT, REL_Y);
+}
+
+void destroy_input_device(int fd)
+{
+	SAFE_IOCTL(fd, UI_DEV_DESTROY, NULL);
+	SAFE_CLOSE(fd);
+}
+
+void create_input_device(int fd)
+{
+	int nb;
+	struct uinput_user_dev uidev = {
+		.name = VIRTUAL_DEVICE,
+		.id = {
+			.bustype = BUS_USB,
+			.vendor = 0x1,
+			.product = 0x1,
+			.version = 1,
+		}
+	};
+
+	SAFE_WRITE(1, fd, &uidev, sizeof(uidev));
+	SAFE_IOCTL(fd, UI_DEV_CREATE, NULL);
+
+	for (nb = 100; nb > 0; nb--) {
+		if (check_device())
+			return;
+		usleep(10000);
+	}
+
+	destroy_input_device(fd);
+	tst_brk(TBROK, "Failed to create device");
+}
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 5/5] kernel/uevent: Add uevent03
  2019-08-26 14:01 [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Cyril Hrubis
                   ` (3 preceding siblings ...)
  2019-08-26 14:01 ` [LTP] [PATCH v3 4/5] libs/libltpuinput: Add uinput library Cyril Hrubis
@ 2019-08-26 14:01 ` Cyril Hrubis
  2019-08-26 15:52   ` Clemens Famulla-Conrad
  2019-08-26 15:59 ` [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Clemens Famulla-Conrad
  5 siblings, 1 reply; 13+ messages in thread
From: Cyril Hrubis @ 2019-08-26 14:01 UTC (permalink / raw)
  To: ltp

This time we create a virtual input device, a mouse, and validate the result.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 runtest/uevent                      |   1 +
 testcases/kernel/uevents/.gitignore |   1 +
 testcases/kernel/uevents/Makefile   |   4 +
 testcases/kernel/uevents/uevent03.c | 248 ++++++++++++++++++++++++++++
 4 files changed, 254 insertions(+)
 create mode 100644 testcases/kernel/uevents/uevent03.c

diff --git a/runtest/uevent b/runtest/uevent
index 30b1114a4..0b59c8723 100644
--- a/runtest/uevent
+++ b/runtest/uevent
@@ -1,2 +1,3 @@
 uevent01 uevent01
 uevent02 uevent02
+uevent03 uevent03
diff --git a/testcases/kernel/uevents/.gitignore b/testcases/kernel/uevents/.gitignore
index 0afc95534..7818f7308 100644
--- a/testcases/kernel/uevents/.gitignore
+++ b/testcases/kernel/uevents/.gitignore
@@ -1,2 +1,3 @@
 uevent01
 uevent02
+uevent03
diff --git a/testcases/kernel/uevents/Makefile b/testcases/kernel/uevents/Makefile
index cba769739..d5ceb0719 100644
--- a/testcases/kernel/uevents/Makefile
+++ b/testcases/kernel/uevents/Makefile
@@ -2,5 +2,9 @@
 
 top_srcdir			?= ../../..
 
+LTPLIBS = ltpuinput
+
+uevent03: LDLIBS += -lltpuinput
+
 include $(top_srcdir)/include/mk/testcases.mk
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/uevents/uevent03.c b/testcases/kernel/uevents/uevent03.c
new file mode 100644
index 000000000..991737e20
--- /dev/null
+++ b/testcases/kernel/uevents/uevent03.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*
+ * Very simple uevent netlink socket test.
+ *
+ * We fork a child that listens for a kernel events while parents creates and
+ * removes a virtual mouse which produces add and remove event for the device
+ * itself and for two event handlers called eventX and mouseY.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <sys/sysmacros.h>
+
+#include <linux/uinput.h>
+
+#include "tst_test.h"
+#include "tst_uinput.h"
+#include "uevent.h"
+
+static int mouse_fd;
+
+static void create_uinput_mouse(void)
+{
+	mouse_fd = open_uinput();
+	setup_mouse_events(mouse_fd);
+	create_input_device(mouse_fd);
+}
+
+static void destroy_uinput_mouse(void)
+{
+	destroy_input_device(mouse_fd);
+}
+
+static void get_minor_major(char *device, char *minor, char *major, size_t buf_sizes)
+{
+	char path[1024];
+	struct stat stbuf;
+
+	snprintf(path, sizeof(path), "/dev/input/%s", device);
+
+	SAFE_STAT(path, &stbuf);
+
+	snprintf(major, buf_sizes, "MAJOR=%i", major(stbuf.st_rdev));
+	snprintf(minor, buf_sizes, "MINOR=%i", minor(stbuf.st_rdev));
+}
+
+#define MINOR_MAJOR_SIZE 32
+
+static void verify_uevent(void)
+{
+	int pid, fd;
+	char sysname[64];
+	char add_msg[1024];
+	char rem_msg[1024];
+	char dev_path[1024];
+	char add_msg_event1[1024];
+	char rem_msg_event1[1024];
+	char dev_path_event1[1024];
+	char add_msg_event2[1024];
+	char rem_msg_event2[1024];
+	char dev_path_event2[1024];
+	char dev_name1[1024];
+	char dev_name2[1024];
+
+	char minor_event1[MINOR_MAJOR_SIZE];
+	char minor_event2[MINOR_MAJOR_SIZE];
+	char major_event1[MINOR_MAJOR_SIZE];
+	char major_event2[MINOR_MAJOR_SIZE];
+
+	char *handlers, *handler1, *handler2;
+
+	struct uevent_desc add = {
+		.msg = add_msg,
+		.value_cnt = 7,
+		.values = (const char*[]) {
+			"ACTION=add",
+			dev_path,
+			"SUBSYSTEM=input",
+			"NAME=\"virtual-device-ltp\"",
+			"PROP=0",
+			"EV=7",
+			"REL=3",
+		}
+	};
+
+	struct uevent_desc add_event1 = {
+		.msg = add_msg_event1,
+		.value_cnt = 6,
+		.values = (const char*[]) {
+			"ACTION=add",
+			"SUBSYSTEM=input",
+			dev_name1,
+			dev_path_event1,
+			minor_event1,
+			major_event1,
+		}
+	};
+
+	struct uevent_desc add_event2 = {
+		.msg = add_msg_event2,
+		.value_cnt = 6,
+		.values = (const char*[]) {
+			"ACTION=add",
+			"SUBSYSTEM=input",
+			dev_name2,
+			dev_path_event2,
+			minor_event2,
+			major_event2,
+		}
+	};
+
+	struct uevent_desc rem_event1 = {
+		.msg = rem_msg_event1,
+		.value_cnt = 6,
+		.values = (const char*[]) {
+			"ACTION=remove",
+			"SUBSYSTEM=input",
+			dev_name1,
+			dev_path_event1,
+			minor_event1,
+			major_event1,
+		}
+	};
+
+	struct uevent_desc rem_event2 = {
+		.msg = rem_msg_event2,
+		.value_cnt = 6,
+		.values = (const char*[]) {
+			"ACTION=remove",
+			"SUBSYSTEM=input",
+			dev_name2,
+			dev_path_event2,
+			minor_event2,
+			major_event2,
+		}
+	};
+
+	struct uevent_desc rem = {
+		.msg = rem_msg,
+		.value_cnt = 7,
+		.values = (const char*[]) {
+			"ACTION=remove",
+			dev_path,
+			"SUBSYSTEM=input",
+			"NAME=\"virtual-device-ltp\"",
+			"PROP=0",
+			"EV=7",
+			"REL=3",
+		}
+	};
+
+	const struct uevent_desc *const uevents[] = {
+		&add,
+		&add_event1,
+		&add_event2,
+		&rem_event1,
+		&rem_event2,
+		&rem,
+		NULL
+	};
+
+	fd = open_uevent_netlink();
+
+	create_uinput_mouse();
+
+	SAFE_IOCTL(mouse_fd, UI_GET_SYSNAME(sizeof(sysname)), sysname);
+	handlers = get_input_handlers();
+
+	tst_res(TINFO, "Sysname: %s", sysname);
+	tst_res(TINFO, "Handlers: %s", handlers);
+
+	handler1 = strtok(handlers, " ");
+	if (!handler1)
+		tst_brk(TBROK, "Expected mouseX and eventY handlers!");
+
+	get_minor_major(handler1, minor_event1, major_event1, MINOR_MAJOR_SIZE);
+
+	handler2 = strtok(NULL, " ");
+	if (!handler2)
+		tst_brk(TBROK, "Expected mouseX and eventY handlers!");
+
+	get_minor_major(handler2, minor_event2, major_event2, MINOR_MAJOR_SIZE);
+
+	destroy_uinput_mouse();
+
+	snprintf(add_msg, sizeof(add_msg),
+	         "add@/devices/virtual/input/%s", sysname);
+
+	snprintf(rem_msg, sizeof(rem_msg),
+	         "remove@/devices/virtual/input/%s", sysname);
+
+	snprintf(dev_path, sizeof(dev_path),
+	         "DEVPATH=/devices/virtual/input/%s", sysname);
+
+
+	snprintf(add_msg_event1, sizeof(add_msg_event1),
+	         "add@/devices/virtual/input/%s/%s", sysname, handler1);
+
+	snprintf(rem_msg_event1, sizeof(rem_msg_event1),
+	         "remove@/devices/virtual/input/%s/%s", sysname, handler1);
+
+	snprintf(dev_path_event1, sizeof(dev_path_event1),
+	         "DEVPATH=/devices/virtual/input/%s/%s", sysname, handler1);
+
+	snprintf(dev_name1, sizeof(dev_name1),
+	         "DEVNAME=input/%s", handler1);
+
+
+	snprintf(add_msg_event2, sizeof(add_msg_event2),
+	         "add@/devices/virtual/input/%s/%s", sysname, handler2);
+
+	snprintf(rem_msg_event2, sizeof(rem_msg_event2),
+	         "remove@/devices/virtual/input/%s/%s", sysname, handler2);
+
+	snprintf(dev_path_event2, sizeof(dev_path_event2),
+	         "DEVPATH=/devices/virtual/input/%s/%s", sysname, handler2);
+
+	snprintf(dev_name2, sizeof(dev_name2),
+	         "DEVNAME=input/%s", handler2);
+
+	free(handlers);
+
+	pid = SAFE_FORK();
+	if (!pid) {
+		wait_for_uevents(fd, uevents);
+		exit(0);
+	}
+
+	SAFE_CLOSE(fd);
+	wait_for_pid(pid);
+}
+
+static struct tst_test test = {
+	.test_all = verify_uevent,
+	.forks_child = 1,
+	.needs_tmpdir = 1,
+	.needs_checkpoints = 1,
+	.needs_drivers = (const char *const[]) {
+		"uinput",
+		NULL
+	},
+	.needs_root = 1,
+};
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 5/5] kernel/uevent: Add uevent03
  2019-08-26 14:01 ` [LTP] [PATCH v3 5/5] kernel/uevent: Add uevent03 Cyril Hrubis
@ 2019-08-26 15:52   ` Clemens Famulla-Conrad
  0 siblings, 0 replies; 13+ messages in thread
From: Clemens Famulla-Conrad @ 2019-08-26 15:52 UTC (permalink / raw)
  To: ltp

Reviewed-by: Clemens Famulla-Conrad <cfamullaconrad@suse.de>

On Mon, 2019-08-26 at 16:01 +0200, Cyril Hrubis wrote:
> This time we create a virtual input device, a mouse, and validate the
> result.
> 
> Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
> ---
>  runtest/uevent                      |   1 +
>  testcases/kernel/uevents/.gitignore |   1 +
>  testcases/kernel/uevents/Makefile   |   4 +
>  testcases/kernel/uevents/uevent03.c | 248
> ++++++++++++++++++++++++++++
>  4 files changed, 254 insertions(+)
>  create mode 100644 testcases/kernel/uevents/uevent03.c
> 
> diff --git a/runtest/uevent b/runtest/uevent
> index 30b1114a4..0b59c8723 100644
> --- a/runtest/uevent
> +++ b/runtest/uevent
> @@ -1,2 +1,3 @@
>  uevent01 uevent01
>  uevent02 uevent02
> +uevent03 uevent03
> diff --git a/testcases/kernel/uevents/.gitignore
> b/testcases/kernel/uevents/.gitignore
> index 0afc95534..7818f7308 100644
> --- a/testcases/kernel/uevents/.gitignore
> +++ b/testcases/kernel/uevents/.gitignore
> @@ -1,2 +1,3 @@
>  uevent01
>  uevent02
> +uevent03
> diff --git a/testcases/kernel/uevents/Makefile
> b/testcases/kernel/uevents/Makefile
> index cba769739..d5ceb0719 100644
> --- a/testcases/kernel/uevents/Makefile
> +++ b/testcases/kernel/uevents/Makefile
> @@ -2,5 +2,9 @@
>  
>  top_srcdir			?= ../../..
>  
> +LTPLIBS = ltpuinput
> +
> +uevent03: LDLIBS += -lltpuinput
> +
>  include $(top_srcdir)/include/mk/testcases.mk
>  include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/uevents/uevent03.c
> b/testcases/kernel/uevents/uevent03.c
> new file mode 100644
> index 000000000..991737e20
> --- /dev/null
> +++ b/testcases/kernel/uevents/uevent03.c
> @@ -0,0 +1,248 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
> + */
> +
> +/*
> + * Very simple uevent netlink socket test.
> + *
> + * We fork a child that listens for a kernel events while parents
> creates and
> + * removes a virtual mouse which produces add and remove event for
> the device
> + * itself and for two event handlers called eventX and mouseY.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/wait.h>
> +#include <sys/sysmacros.h>
> +
> +#include <linux/uinput.h>
> +
> +#include "tst_test.h"
> +#include "tst_uinput.h"
> +#include "uevent.h"
> +
> +static int mouse_fd;
> +
> +static void create_uinput_mouse(void)
> +{
> +	mouse_fd = open_uinput();
> +	setup_mouse_events(mouse_fd);
> +	create_input_device(mouse_fd);
> +}
> +
> +static void destroy_uinput_mouse(void)
> +{
> +	destroy_input_device(mouse_fd);
> +}
> +
> +static void get_minor_major(char *device, char *minor, char *major,
> size_t buf_sizes)
> +{
> +	char path[1024];
> +	struct stat stbuf;
> +
> +	snprintf(path, sizeof(path), "/dev/input/%s", device);
> +
> +	SAFE_STAT(path, &stbuf);
> +
> +	snprintf(major, buf_sizes, "MAJOR=%i",
> major(stbuf.st_rdev));
> +	snprintf(minor, buf_sizes, "MINOR=%i",
> minor(stbuf.st_rdev));
> +}
> +
> +#define MINOR_MAJOR_SIZE 32
> +
> +static void verify_uevent(void)
> +{
> +	int pid, fd;
> +	char sysname[64];
> +	char add_msg[1024];
> +	char rem_msg[1024];
> +	char dev_path[1024];
> +	char add_msg_event1[1024];
> +	char rem_msg_event1[1024];
> +	char dev_path_event1[1024];
> +	char add_msg_event2[1024];
> +	char rem_msg_event2[1024];
> +	char dev_path_event2[1024];
> +	char dev_name1[1024];
> +	char dev_name2[1024];
> +
> +	char minor_event1[MINOR_MAJOR_SIZE];
> +	char minor_event2[MINOR_MAJOR_SIZE];
> +	char major_event1[MINOR_MAJOR_SIZE];
> +	char major_event2[MINOR_MAJOR_SIZE];
> +
> +	char *handlers, *handler1, *handler2;
> +
> +	struct uevent_desc add = {
> +		.msg = add_msg,
> +		.value_cnt = 7,
> +		.values = (const char*[]) {
> +			"ACTION=add",
> +			dev_path,
> +			"SUBSYSTEM=input",
> +			"NAME=\"virtual-device-ltp\"",
> +			"PROP=0",
> +			"EV=7",
> +			"REL=3",
> +		}
> +	};
> +
> +	struct uevent_desc add_event1 = {
> +		.msg = add_msg_event1,
> +		.value_cnt = 6,
> +		.values = (const char*[]) {
> +			"ACTION=add",
> +			"SUBSYSTEM=input",
> +			dev_name1,
> +			dev_path_event1,
> +			minor_event1,
> +			major_event1,
> +		}
> +	};
> +
> +	struct uevent_desc add_event2 = {
> +		.msg = add_msg_event2,
> +		.value_cnt = 6,
> +		.values = (const char*[]) {
> +			"ACTION=add",
> +			"SUBSYSTEM=input",
> +			dev_name2,
> +			dev_path_event2,
> +			minor_event2,
> +			major_event2,
> +		}
> +	};
> +
> +	struct uevent_desc rem_event1 = {
> +		.msg = rem_msg_event1,
> +		.value_cnt = 6,
> +		.values = (const char*[]) {
> +			"ACTION=remove",
> +			"SUBSYSTEM=input",
> +			dev_name1,
> +			dev_path_event1,
> +			minor_event1,
> +			major_event1,
> +		}
> +	};
> +
> +	struct uevent_desc rem_event2 = {
> +		.msg = rem_msg_event2,
> +		.value_cnt = 6,
> +		.values = (const char*[]) {
> +			"ACTION=remove",
> +			"SUBSYSTEM=input",
> +			dev_name2,
> +			dev_path_event2,
> +			minor_event2,
> +			major_event2,
> +		}
> +	};
> +
> +	struct uevent_desc rem = {
> +		.msg = rem_msg,
> +		.value_cnt = 7,
> +		.values = (const char*[]) {
> +			"ACTION=remove",
> +			dev_path,
> +			"SUBSYSTEM=input",
> +			"NAME=\"virtual-device-ltp\"",
> +			"PROP=0",
> +			"EV=7",
> +			"REL=3",
> +		}
> +	};
> +
> +	const struct uevent_desc *const uevents[] = {
> +		&add,
> +		&add_event1,
> +		&add_event2,
> +		&rem_event1,
> +		&rem_event2,
> +		&rem,
> +		NULL
> +	};
> +
> +	fd = open_uevent_netlink();
> +
> +	create_uinput_mouse();
> +
> +	SAFE_IOCTL(mouse_fd, UI_GET_SYSNAME(sizeof(sysname)),
> sysname);
> +	handlers = get_input_handlers();
> +
> +	tst_res(TINFO, "Sysname: %s", sysname);
> +	tst_res(TINFO, "Handlers: %s", handlers);
> +
> +	handler1 = strtok(handlers, " ");
> +	if (!handler1)
> +		tst_brk(TBROK, "Expected mouseX and eventY
> handlers!");
> +
> +	get_minor_major(handler1, minor_event1, major_event1,
> MINOR_MAJOR_SIZE);
> +
> +	handler2 = strtok(NULL, " ");
> +	if (!handler2)
> +		tst_brk(TBROK, "Expected mouseX and eventY
> handlers!");
> +
> +	get_minor_major(handler2, minor_event2, major_event2,
> MINOR_MAJOR_SIZE);
> +
> +	destroy_uinput_mouse();
> +
> +	snprintf(add_msg, sizeof(add_msg),
> +	         "add@/devices/virtual/input/%s", sysname);
> +
> +	snprintf(rem_msg, sizeof(rem_msg),
> +	         "remove@/devices/virtual/input/%s", sysname);
> +
> +	snprintf(dev_path, sizeof(dev_path),
> +	         "DEVPATH=/devices/virtual/input/%s", sysname);
> +
> +
> +	snprintf(add_msg_event1, sizeof(add_msg_event1),
> +	         "add@/devices/virtual/input/%s/%s", sysname,
> handler1);
> +
> +	snprintf(rem_msg_event1, sizeof(rem_msg_event1),
> +	         "remove@/devices/virtual/input/%s/%s", sysname,
> handler1);
> +
> +	snprintf(dev_path_event1, sizeof(dev_path_event1),
> +	         "DEVPATH=/devices/virtual/input/%s/%s", sysname,
> handler1);
> +
> +	snprintf(dev_name1, sizeof(dev_name1),
> +	         "DEVNAME=input/%s", handler1);
> +
> +
> +	snprintf(add_msg_event2, sizeof(add_msg_event2),
> +	         "add@/devices/virtual/input/%s/%s", sysname,
> handler2);
> +
> +	snprintf(rem_msg_event2, sizeof(rem_msg_event2),
> +	         "remove@/devices/virtual/input/%s/%s", sysname,
> handler2);
> +
> +	snprintf(dev_path_event2, sizeof(dev_path_event2),
> +	         "DEVPATH=/devices/virtual/input/%s/%s", sysname,
> handler2);
> +
> +	snprintf(dev_name2, sizeof(dev_name2),
> +	         "DEVNAME=input/%s", handler2);
> +
> +	free(handlers);
> +
> +	pid = SAFE_FORK();
> +	if (!pid) {
> +		wait_for_uevents(fd, uevents);
> +		exit(0);
> +	}
> +
> +	SAFE_CLOSE(fd);
> +	wait_for_pid(pid);
> +}
> +
> +static struct tst_test test = {
> +	.test_all = verify_uevent,
> +	.forks_child = 1,
> +	.needs_tmpdir = 1,
> +	.needs_checkpoints = 1,
> +	.needs_drivers = (const char *const[]) {
> +		"uinput",
> +		NULL
> +	},
> +	.needs_root = 1,
> +};
> -- 
> 2.21.0
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 4/5] libs/libltpuinput: Add uinput library.
  2019-08-26 14:01 ` [LTP] [PATCH v3 4/5] libs/libltpuinput: Add uinput library Cyril Hrubis
@ 2019-08-26 15:55   ` Clemens Famulla-Conrad
  0 siblings, 0 replies; 13+ messages in thread
From: Clemens Famulla-Conrad @ 2019-08-26 15:55 UTC (permalink / raw)
  To: ltp

Reviewed-by: Clemens Famulla-Conrad <cfamullaconrad@suse.de>

On Mon, 2019-08-26 at 16:01 +0200, Cyril Hrubis wrote:
> I to be used in the uevent03 test.
> 
> Also I will convert the uinput testcases to new library and make use
> of
> this library as well.
> 
> Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
> ---
>  include/tst_uinput.h           |  48 +++++++++++
>  libs/libltpuinput/Makefile     |  12 +++
>  libs/libltpuinput/tst_uinput.c | 143
> +++++++++++++++++++++++++++++++++
>  3 files changed, 203 insertions(+)
>  create mode 100644 include/tst_uinput.h
>  create mode 100644 libs/libltpuinput/Makefile
>  create mode 100644 libs/libltpuinput/tst_uinput.c
> 
> diff --git a/include/tst_uinput.h b/include/tst_uinput.h
> new file mode 100644
> index 000000000..dddbd9921
> --- /dev/null
> +++ b/include/tst_uinput.h
> @@ -0,0 +1,48 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
> + */
> +
> +#ifndef TST_UINPUT_H__
> +#define TST_UINPUT_H__
> +
> +/**
> + * Tries to open the uinput device.
> + *
> + * Returns file descriptor on success, -1 on failure.
> + */
> +int open_uinput(void);
> +
> +/**
> + * Creates virtual input device.
> + *
> + * @fd File descriptor returned by open_uinput().
> + */
> +void create_input_device(int fd);
> +
> +/**
> + * Parses /proc/bus/input/devices and returns the handlers strings
> for our
> + * virtual device, which is list of input devices that receive
> events from the
> + * device separated by whitestpaces.
> + *
> + * Returns newly allocated string, list of handlers separated by
> whitespaces,
> + * or NULL in a case of failure.
> + */
> +char *get_input_handlers(void);
> +
> +/**
> + * Sets up the virtual device to appear as a mouse, this must be
> called before
> + * the call to create_input_device().
> + *
> + * @fd File descriptor as returned by open_uinput().
> + */
> +void setup_mouse_events(int fd);
> +
> +/**
> + * Destroys virtual input device.
> + *
> + * @fd File descriptor returned by open_uinput().
> + */
> +void destroy_input_device(int fd);
> +
> +#endif	/* TST_UINPUT_H__ */
> diff --git a/libs/libltpuinput/Makefile b/libs/libltpuinput/Makefile
> new file mode 100644
> index 000000000..dd2a6c096
> --- /dev/null
> +++ b/libs/libltpuinput/Makefile
> @@ -0,0 +1,12 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Copyright (C) Cyril Hrubis <chrubis@suse.cz>
> +
> +top_srcdir		?= ../..
> +
> +include $(top_srcdir)/include/mk/env_pre.mk
> +
> +LIB			:= libltpuinput.a
> +
> +include $(top_srcdir)/include/mk/lib.mk
> +include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/libs/libltpuinput/tst_uinput.c
> b/libs/libltpuinput/tst_uinput.c
> new file mode 100644
> index 000000000..4b22fef2a
> --- /dev/null
> +++ b/libs/libltpuinput/tst_uinput.c
> @@ -0,0 +1,143 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com>
> + * Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
> + */
> +
> +#include <linux/input.h>
> +#include <linux/uinput.h>
> +#include <stdio.h>
> +#include <string.h>
> +
> +#define TST_NO_DEFAULT_MAIN
> +#include "tst_test.h"
> +
> +#include "tst_uinput.h"
> +
> +#define VIRTUAL_DEVICE "virtual-device-ltp"
> +
> +static const char *uinput_paths[] = {
> +	"/dev/input/uinput",
> +	"/dev/uinput",
> +};
> +
> +int open_uinput(void)
> +{
> +	unsigned int i;
> +	int fd;
> +
> +	for (i = 0; i < ARRAY_SIZE(uinput_paths); i++) {
> +		fd = open(uinput_paths[i], O_WRONLY | O_NONBLOCK);
> +
> +		if (fd > 0) {
> +			tst_res(TINFO, "Found uinput dev at %s",
> uinput_paths[i]);
> +			return fd;
> +		}
> +
> +		if (fd < 0 && errno != ENOENT) {
> +			tst_brk(TBROK | TERRNO, "open(%s)",
> uinput_paths[i]);
> +		}
> +	}
> +
> +	return -1;
> +}
> +
> +#define HANDLERS_PREFIX "Handlers="
> +
> +static char *parse_handlers(char *line)
> +{
> +	char *handlers;
> +
> +	handlers = strstr(line, HANDLERS_PREFIX) +
> sizeof(HANDLERS_PREFIX) - 1;
> +
> +	handlers[strlen(handlers) - 1] = 0;
> +
> +	return strdup(handlers);
> +}
> +
> +char *get_input_handlers(void)
> +{
> +	FILE *file;
> +	char line[1024];
> +	int flag = 0;
> +
> +	file = fopen("/proc/bus/input/devices", "r");
> +	if (!file)
> +		return NULL;
> +
> +	while (fgets(line, sizeof(line), file)) {
> +		if (strstr(line, "N: Name=\""VIRTUAL_DEVICE"\""))
> +			flag = 1;
> +
> +		if (flag) {
> +			if (line[0] == 'H')
> +				return parse_handlers(line);
> +
> +			if (line[0] == '\n')
> +				flag = 0;
> +		}
> +	}
> +
> +	fclose(file);
> +	return NULL;
> +}
> +
> +static int check_device(void)
> +{
> +	FILE *file;
> +	char line[256];
> +
> +	file = fopen("/proc/bus/input/devices", "r");
> +	if (!file)
> +		return 0;
> +
> +	while (fgets(line, sizeof(line), file)) {
> +		if (strstr(line, "Name=\""VIRTUAL_DEVICE"\""))
> +			return 1;
> +	}
> +
> +	fclose(file);
> +
> +	return 0;
> +}
> +
> +void setup_mouse_events(int fd)
> +{
> +	SAFE_IOCTL(fd, UI_SET_EVBIT, EV_KEY);
> +	SAFE_IOCTL(fd, UI_SET_KEYBIT, BTN_LEFT);
> +	SAFE_IOCTL(fd, UI_SET_EVBIT, EV_REL);
> +	SAFE_IOCTL(fd, UI_SET_RELBIT, REL_X);
> +	SAFE_IOCTL(fd, UI_SET_RELBIT, REL_Y);
> +}
> +
> +void destroy_input_device(int fd)
> +{
> +	SAFE_IOCTL(fd, UI_DEV_DESTROY, NULL);
> +	SAFE_CLOSE(fd);
> +}
> +
> +void create_input_device(int fd)
> +{
> +	int nb;
> +	struct uinput_user_dev uidev = {
> +		.name = VIRTUAL_DEVICE,
> +		.id = {
> +			.bustype = BUS_USB,
> +			.vendor = 0x1,
> +			.product = 0x1,
> +			.version = 1,
> +		}
> +	};
> +
> +	SAFE_WRITE(1, fd, &uidev, sizeof(uidev));
> +	SAFE_IOCTL(fd, UI_DEV_CREATE, NULL);
> +
> +	for (nb = 100; nb > 0; nb--) {
> +		if (check_device())
> +			return;
> +		usleep(10000);
> +	}
> +
> +	destroy_input_device(fd);
> +	tst_brk(TBROK, "Failed to create device");
> +}
> -- 
> 2.21.0
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 3/5] kernel/uevent: Add uevent02
  2019-08-26 14:01 ` [LTP] [PATCH v3 3/5] kernel/uevent: Add uevent02 Cyril Hrubis
@ 2019-08-26 15:55   ` Clemens Famulla-Conrad
  0 siblings, 0 replies; 13+ messages in thread
From: Clemens Famulla-Conrad @ 2019-08-26 15:55 UTC (permalink / raw)
  To: ltp

Reviewed-by: Clemens Famulla-Conrad <cfamullaconrad@suse.de>

On Mon, 2019-08-26 at 16:01 +0200, Cyril Hrubis wrote:
> Similar to uevent01 but we create and remove a tun network card
> instead.
> 
> Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
> ---
>  runtest/uevent                      |   1 +
>  testcases/kernel/uevents/.gitignore |   1 +
>  testcases/kernel/uevents/uevent02.c | 143
> ++++++++++++++++++++++++++++
>  3 files changed, 145 insertions(+)
>  create mode 100644 testcases/kernel/uevents/uevent02.c
> 
> diff --git a/runtest/uevent b/runtest/uevent
> index e9cdf26b8..30b1114a4 100644
> --- a/runtest/uevent
> +++ b/runtest/uevent
> @@ -1 +1,2 @@
>  uevent01 uevent01
> +uevent02 uevent02
> diff --git a/testcases/kernel/uevents/.gitignore
> b/testcases/kernel/uevents/.gitignore
> index 53d0b546a..0afc95534 100644
> --- a/testcases/kernel/uevents/.gitignore
> +++ b/testcases/kernel/uevents/.gitignore
> @@ -1 +1,2 @@
>  uevent01
> +uevent02
> diff --git a/testcases/kernel/uevents/uevent02.c
> b/testcases/kernel/uevents/uevent02.c
> new file mode 100644
> index 000000000..b94748c51
> --- /dev/null
> +++ b/testcases/kernel/uevents/uevent02.c
> @@ -0,0 +1,143 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
> + */
> +
> +/*
> + * Very simple uevent netlink socket test.
> + *
> + * We fork a child that listens for a kernel events while parents
> creates and
> + * removes a tun network device which should produce two several add
> and remove
> + * events.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/wait.h>
> +#include <linux/if.h>
> +#include <linux/if_tun.h>
> +
> +#include "tst_test.h"
> +
> +#include "uevent.h"
> +
> +#define TUN_PATH "/dev/net/tun"
> +
> +static void generate_tun_uevents(void)
> +{
> +	int fd = SAFE_OPEN(TUN_PATH, O_RDWR);
> +
> +	struct ifreq ifr = {
> +		.ifr_flags = IFF_TUN,
> +		.ifr_name = "ltp-tun0",
> +	};
> +
> +	SAFE_IOCTL(fd, TUNSETIFF, (void*)&ifr);
> +
> +	SAFE_IOCTL(fd, TUNSETPERSIST, 0);
> +
> +	SAFE_CLOSE(fd);
> +}
> +
> +static void verify_uevent(void)
> +{
> +	int pid, fd;
> +
> +	struct uevent_desc add = {
> +		.msg = "add@/devices/virtual/net/ltp-tun0",
> +		.value_cnt = 4,
> +		.values = (const char*[]) {
> +			"ACTION=add",
> +			"DEVPATH=/devices/virtual/net/ltp-tun0",
> +			"SUBSYSTEM=net",
> +			"INTERFACE=ltp-tun0",
> +		}
> +	};
> +
> +	struct uevent_desc add_rx = {
> +		.msg = "add@/devices/virtual/net/ltp-tun0/queues/rx-
> 0",
> +		.value_cnt = 3,
> +		.values = (const char*[]) {
> +			"ACTION=add",
> +			"DEVPATH=/devices/virtual/net/ltp-
> tun0/queues/rx-0",
> +			"SUBSYSTEM=queues",
> +		}
> +	};
> +
> +	struct uevent_desc add_tx = {
> +		.msg = "add@/devices/virtual/net/ltp-tun0/queues/tx-
> 0",
> +		.value_cnt = 3,
> +		.values = (const char*[]) {
> +			"ACTION=add",
> +			"DEVPATH=/devices/virtual/net/ltp-
> tun0/queues/tx-0",
> +			"SUBSYSTEM=queues",
> +		}
> +	};
> +
> +	struct uevent_desc rem_rx = {
> +		.msg = "remove@/devices/virtual/net/ltp-
> tun0/queues/rx-0",
> +		.value_cnt = 3,
> +		.values = (const char*[]) {
> +			"ACTION=remove",
> +			"DEVPATH=/devices/virtual/net/ltp-
> tun0/queues/rx-0",
> +			"SUBSYSTEM=queues",
> +		}
> +	};
> +
> +	struct uevent_desc rem_tx = {
> +		.msg = "remove@/devices/virtual/net/ltp-
> tun0/queues/tx-0",
> +		.value_cnt = 3,
> +		.values = (const char*[]) {
> +			"ACTION=remove",
> +			"DEVPATH=/devices/virtual/net/ltp-
> tun0/queues/tx-0",
> +			"SUBSYSTEM=queues",
> +		}
> +	};
> +
> +	struct uevent_desc rem = {
> +		.msg = "remove@/devices/virtual/net/ltp-tun0",
> +		.value_cnt = 4,
> +		.values = (const char*[]) {
> +			"ACTION=remove",
> +			"DEVPATH=/devices/virtual/net/ltp-tun0",
> +			"SUBSYSTEM=net",
> +			"INTERFACE=ltp-tun0",
> +		}
> +	};
> +
> +	const struct uevent_desc *const uevents[] = {
> +		&add,
> +		&add_rx,
> +		&add_tx,
> +		&rem_rx,
> +		&rem_tx,
> +		&rem,
> +		NULL
> +	};
> +
> +	pid = SAFE_FORK();
> +	if (!pid) {
> +		fd = open_uevent_netlink();
> +		TST_CHECKPOINT_WAKE(0);
> +		wait_for_uevents(fd, uevents);
> +		exit(0);
> +	}
> +
> +	TST_CHECKPOINT_WAIT(0);
> +
> +	generate_tun_uevents();
> +
> +	wait_for_pid(pid);
> +}
> +
> +static struct tst_test test = {
> +	.test_all = verify_uevent,
> +	.forks_child = 1,
> +	.needs_tmpdir = 1,
> +	.needs_checkpoints = 1,
> +	.needs_drivers = (const char *const []) {
> +		"tun",
> +		NULL
> +	},
> +	.needs_root = 1
> +};
> -- 
> 2.21.0
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 1/5] lib/tst_device: Export more functions.
  2019-08-26 14:01 ` [LTP] [PATCH v3 1/5] lib/tst_device: Export more functions Cyril Hrubis
@ 2019-08-26 15:57   ` Clemens Famulla-Conrad
  2019-09-02 13:02     ` Cyril Hrubis
  0 siblings, 1 reply; 13+ messages in thread
From: Clemens Famulla-Conrad @ 2019-08-26 15:57 UTC (permalink / raw)
  To: ltp

Hi Cyril,
I just realized that copyright date might need an update
and there are no function desc in tst_device.h.

On Mon, 2019-08-26 at 16:01 +0200, Cyril Hrubis wrote:
> Export tst_attach_device() and tst_deteach_device() which will be
> later
> on used by a kernel netlink uevent tests.
> 
> Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
> Reviewed-by: Clemens Famulla-Conrad <cfamullaconrad@suse.de>
> ---
>  include/tst_device.h | 7 +++++++
>  lib/tst_device.c     | 8 ++++----
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/include/tst_device.h b/include/tst_device.h
> index f0ddc3e93..c6e7b45b1 100644
> --- a/include/tst_device.h
> +++ b/include/tst_device.h
> @@ -50,6 +50,13 @@ int tst_clear_device(const char *dev);
>   *
>   */
>  int tst_find_free_loopdev(const char *path, size_t path_len);
> +
> +
> +int tst_attach_device(const char *dev_path, const char *file_path);
> +
> +
> +int tst_detach_device(const char *dev_path);
> +
>  /*
>   * Reads test block device stat file and returns the bytes written
> since the
>   * last call of this function.
> diff --git a/lib/tst_device.c b/lib/tst_device.c
> index 22abdef46..10f71901d 100644
> --- a/lib/tst_device.c
> +++ b/lib/tst_device.c
> @@ -139,7 +139,7 @@ int tst_find_free_loopdev(char *path, size_t
> path_len)
>  	return -1;
>  }
>  
> -static int attach_device(const char *dev, const char *file)
> +int tst_attach_device(const char *dev, const char *file)
>  {
>  	int dev_fd, file_fd;
>  	struct loop_info loopinfo;
> @@ -185,7 +185,7 @@ static int attach_device(const char *dev, const
> char *file)
>  	return 0;
>  }
>  
> -static int detach_device(const char *dev)
> +int tst_detach_device(const char *dev)
>  {
>  	int dev_fd, ret, i;
>  
> @@ -284,7 +284,7 @@ const char *tst_acquire_device__(unsigned int
> size)
>  	if (tst_find_free_loopdev(dev_path, sizeof(dev_path)) == -1)
>  		return NULL;
>  
> -	if (attach_device(dev_path, DEV_FILE))
> +	if (tst_attach_device(dev_path, DEV_FILE))
>  		return NULL;
>  
>  	device_acquired = 1;
> @@ -329,7 +329,7 @@ int tst_release_device(const char *dev)
>  	 *
>  	 * The file image is deleted in tst_rmdir();
>  	 */
> -	ret = detach_device(dev);
> +	ret = tst_detach_device(dev);
>  
>  	device_acquired = 0;
>  

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 2/5] kernel/uevent: Add uevent01
  2019-08-26 14:01 ` [LTP] [PATCH v3 2/5] kernel/uevent: Add uevent01 Cyril Hrubis
@ 2019-08-26 15:57   ` Clemens Famulla-Conrad
  0 siblings, 0 replies; 13+ messages in thread
From: Clemens Famulla-Conrad @ 2019-08-26 15:57 UTC (permalink / raw)
  To: ltp

Reviewed-by: Clemens Famulla-Conrad <cfamullaconrad@suse.de>

On Mon, 2019-08-26 at 16:01 +0200, Cyril Hrubis wrote:
> Simple test that attached and detaches a file to a loop device and
> checks that kernel broadcasts correct events to the kernel uevent
> broadcast group.
> 
> Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
> ---
>  runtest/uevent                      |   1 +
>  scenario_groups/default             |   1 +
>  testcases/kernel/uevents/.gitignore |   1 +
>  testcases/kernel/uevents/Makefile   |   6 +
>  testcases/kernel/uevents/uevent.h   | 176
> ++++++++++++++++++++++++++++
>  testcases/kernel/uevents/uevent01.c |  98 ++++++++++++++++
>  6 files changed, 283 insertions(+)
>  create mode 100644 runtest/uevent
>  create mode 100644 testcases/kernel/uevents/.gitignore
>  create mode 100644 testcases/kernel/uevents/Makefile
>  create mode 100644 testcases/kernel/uevents/uevent.h
>  create mode 100644 testcases/kernel/uevents/uevent01.c
> 
> diff --git a/runtest/uevent b/runtest/uevent
> new file mode 100644
> index 000000000..e9cdf26b8
> --- /dev/null
> +++ b/runtest/uevent
> @@ -0,0 +1 @@
> +uevent01 uevent01
> diff --git a/scenario_groups/default b/scenario_groups/default
> index 093f5f706..62ae0759d 100644
> --- a/scenario_groups/default
> +++ b/scenario_groups/default
> @@ -29,3 +29,4 @@ input
>  cve
>  crypto
>  kernel_misc
> +uevent
> diff --git a/testcases/kernel/uevents/.gitignore
> b/testcases/kernel/uevents/.gitignore
> new file mode 100644
> index 000000000..53d0b546a
> --- /dev/null
> +++ b/testcases/kernel/uevents/.gitignore
> @@ -0,0 +1 @@
> +uevent01
> diff --git a/testcases/kernel/uevents/Makefile
> b/testcases/kernel/uevents/Makefile
> new file mode 100644
> index 000000000..cba769739
> --- /dev/null
> +++ b/testcases/kernel/uevents/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +top_srcdir			?= ../../..
> +
> +include $(top_srcdir)/include/mk/testcases.mk
> +include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/uevents/uevent.h
> b/testcases/kernel/uevents/uevent.h
> new file mode 100644
> index 000000000..908e150f0
> --- /dev/null
> +++ b/testcases/kernel/uevents/uevent.h
> @@ -0,0 +1,176 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
> + */
> +
> +#ifndef UEVENT_H__
> +#define UEVENT_H__
> +
> +#include "tst_netlink.h"
> +
> +/*
> + * There are two broadcast groups defined for the
> NETLINK_KOBJECT_UEVENT. The
> + * primary consument of the KERNEL group is udev which handles the
> hotplug
> + * events and then, once udev does it's magic the events are
> rebroadcasted to
> + * the UDEV group which is consumed by various daemons in the
> userspace.
> + */
> +enum monitor_netlink_group {
> +	MONITOR_GROUP_NONE,
> +	MONITOR_GROUP_KERNEL,
> +	MONITOR_GROUP_UDEV,
> +};
> +
> +/*
> + * The messages received from the NETLINK_KOBJECT_UEVENT socket are
> stored as a
> + * sequence of a null-terminated strings. First in the buffer is a
> summary of a
> + * action i.e. "$ACTION@$DEVPATH" which is then followed by a bunch
> of
> + * key-value pairs.
> + *
> + * For example attaching a file to loopback device generates event:
> + *
> + * "change@/devices/virtual/block/loop0\0
> + *  ACTION=change\0
> + *  DEVPATH=/devices/virtual/block/loop0\0
> + *  SUBSYSTEM=block\0
> + *  MAJOR=7\0
> + *  MINOR=0\0
> + *  DEVNAME=loop0\0
> + *  DEVTYPE=disk\0
> + *  SEQNUM=2677\0"
> + */
> +
> +/*
> + * Prints uevent.
> + */
> +static inline void print_uevent(const char *event, int len)
> +{
> +	int consumed = 0;
> +
> +	tst_res(TINFO, "Got uevent:");
> +
> +	while (consumed < len) {
> +		tst_res(TINFO, "%s", event);
> +		int l = strlen(event) + 1;
> +		consumed += l;
> +		event += l;
> +	}
> +}
> +
> +/*
> + * Uevents read from the socket are matched against this
> description.
> + *
> + * The msg is the overall action description e.g.
> + * "add@/class/input/input4/mouse1" which has to be matched exactly
> before we
> + * event attempt to check the key-value pairs stored in the values
> array. The
> + * event is considered to match if all key-value pairs in the values
> has been
> + * found in the received event.
> + */
> +struct uevent_desc {
> +	const char *msg;
> +	int value_cnt;
> +	const char **values;
> +};
> +
> +static inline int uevent_match(const char *event, int len,
> +                               const struct uevent_desc *uevent)
> +{
> +	int consumed = 0;
> +	int val_matches = 0;
> +
> +	if (memcmp(event, uevent->msg, strlen(uevent->msg)))
> +		return 0;
> +
> +	int l = strlen(event) + 1;
> +
> +	consumed += l;
> +	event += l;
> +
> +	while (consumed < len) {
> +		int i;
> +		for (i = 0; i < uevent->value_cnt; i++) {
> +			if (!strcmp(event, uevent->values[i])) {
> +				val_matches++;
> +				break;
> +			}
> +		}
> +
> +		l = strlen(event) + 1;
> +		consumed += l;
> +		event += l;
> +	}
> +
> +	return val_matches == uevent->value_cnt;
> +}
> +
> +static inline int open_uevent_netlink(void)
> +{
> +	int fd;
> +	struct sockaddr_nl nl_addr = {
> +		.nl_family = AF_NETLINK,
> +		.nl_groups = MONITOR_GROUP_KERNEL,
> +	};
> +
> +	fd = SAFE_SOCKET(AF_NETLINK, SOCK_RAW,
> NETLINK_KOBJECT_UEVENT);
> +
> +	SAFE_BIND(fd, (struct sockaddr *)&nl_addr, sizeof(nl_addr));
> +
> +	return fd;
> +}
> +
> +/*
> + * Reads events from uevent netlink socket until all expected events
> passed in
> + * the uevent array are matched.
> + */
> +static inline void wait_for_uevents(int fd, const struct uevent_desc
> *const uevents[])
> +{
> +	int i = 0;
> +
> +	while (1) {
> +		int len;
> +		char buf[4096];
> +
> +		len = recv(fd, &buf, sizeof(buf), 0);
> +
> +		if (len == 0)
> +			continue;
> +
> +		print_uevent(buf, len);
> +
> +		if (uevent_match(buf, len, uevents[i])) {
> +			tst_res(TPASS, "Got expected UEVENT");
> +			if (!uevents[++i]) {
> +				close(fd);
> +				return;
> +			}
> +		}
> +	}
> +}
> +
> +/*
> + * Waits 5 seconds for a child to exit, kills the child after a
> timeout.
> + */
> +static inline void wait_for_pid(int pid)
> +{
> +	int status, ret;
> +	int retries = 5000;
> +
> +	do {
> +		ret = waitpid(pid, &status, WNOHANG);
> +		usleep(1000);
> +	} while (ret == 0 && retries--);
> +
> +	if (ret == pid) {
> +		if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
> +			return;
> +
> +		tst_res(TFAIL, "Child exitted with %s",
> tst_strstatus(status));
> +	}
> +
> +	SAFE_KILL(pid, SIGKILL);
> +
> +	SAFE_WAITPID(pid, NULL, 0);
> +
> +	tst_res(TFAIL, "Did not get all expected UEVENTS");
> +}
> +
> +#endif /* UEVENT_H__ */
> diff --git a/testcases/kernel/uevents/uevent01.c
> b/testcases/kernel/uevents/uevent01.c
> new file mode 100644
> index 000000000..0dd1344a7
> --- /dev/null
> +++ b/testcases/kernel/uevents/uevent01.c
> @@ -0,0 +1,98 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
> + */
> +
> +/*
> + * Very simple uevent netlink socket test.
> + *
> + * We fork a child that listens for a kernel events while parents
> attaches and
> + * detaches a loop device which should produce two change events.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/wait.h>
> +#include "tst_test.h"
> +
> +#include "uevent.h"
> +
> +static void generate_device_events(const char *dev_path)
> +{
> +	tst_fill_file("loop.img", 0, 1024, 1024);
> +
> +	tst_res(TINFO, "Attaching device %s", dev_path);
> +	tst_attach_device(dev_path, "loop.img");
> +	tst_res(TINFO, "Detaching device %s", dev_path);
> +	tst_detach_device(dev_path);
> +}
> +
> +static void verify_uevent(void)
> +{
> +	int pid, fd, dev_num;
> +	char dev_path[1024];
> +	char ev_msg[1024];
> +	char ev_dev_path[1024];
> +	char ev_dev_minor[128];
> +	char ev_dev_name[128];
> +
> +	struct uevent_desc desc = {
> +		.msg = ev_msg,
> +		.value_cnt = 7,
> +		.values = (const char*[]) {
> +			"ACTION=change",
> +			ev_dev_path,
> +			"SUBSYSTEM=block",
> +			"MAJOR=7",
> +			ev_dev_minor,
> +			ev_dev_name,
> +			"DEVTYPE=disk",
> +		}
> +	};
> +
> +	dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path));
> +
> +	if (dev_num < 0)
> +		tst_brk(TBROK, "Failed to find free loop device");
> +
> +	snprintf(ev_msg, sizeof(ev_msg),
> +	         "change@/devices/virtual/block/loop%i", dev_num);
> +
> +	snprintf(ev_dev_path, sizeof(ev_dev_path),
> +	         "DEVPATH=/devices/virtual/block/loop%i", dev_num);
> +
> +	snprintf(ev_dev_minor, sizeof(ev_dev_minor), "MINOR=%i",
> dev_num);
> +	snprintf(ev_dev_name, sizeof(ev_dev_name), "DEVNAME=loop%i",
> dev_num);
> +
> +	const struct uevent_desc *const uevents[] = {
> +		&desc,
> +		&desc,
> +		NULL
> +	};
> +
> +	pid = SAFE_FORK();
> +	if (!pid) {
> +		fd = open_uevent_netlink();
> +		TST_CHECKPOINT_WAKE(0);
> +		wait_for_uevents(fd, uevents);
> +		exit(0);
> +	}
> +
> +	TST_CHECKPOINT_WAIT(0);
> +
> +	generate_device_events(dev_path);
> +
> +	wait_for_pid(pid);
> +}
> +
> +static struct tst_test test = {
> +	.test_all = verify_uevent,
> +	.forks_child = 1,
> +	.needs_tmpdir = 1,
> +	.needs_checkpoints = 1,
> +	.needs_drivers = (const char *const []) {
> +		"loop",
> +		NULL
> +	},
> +	.needs_root = 1
> +};
> -- 
> 2.21.0
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket
  2019-08-26 14:01 [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Cyril Hrubis
                   ` (4 preceding siblings ...)
  2019-08-26 14:01 ` [LTP] [PATCH v3 5/5] kernel/uevent: Add uevent03 Cyril Hrubis
@ 2019-08-26 15:59 ` Clemens Famulla-Conrad
  5 siblings, 0 replies; 13+ messages in thread
From: Clemens Famulla-Conrad @ 2019-08-26 15:59 UTC (permalink / raw)
  To: ltp

Hi Cyril,
Patch set looks good to me, beside that minor doc stuff in
tst_device.h.

I run all tests on my system (opensuse LEAP 15.1 x86_64), also in
loops.

Thanks
Clemens

On Mon, 2019-08-26 at 16:01 +0200, Cyril Hrubis wrote:
> This patchset adds three basic test for uevent netlink socket.
> 
> v3:
> 
> Fixed all problems pointed out by Clemens.
> 
> v2:
> 
> Finished the input event test, now we match all events.
> 
> *** BLURB HERE ***
> 
> Cyril Hrubis (5):
>   lib/tst_device: Export more functions.
>   kernel/uevent: Add uevent01
>   kernel/uevent: Add uevent02
>   libs/libltpuinput: Add uinput library.
>   kernel/uevent: Add uevent03
> 
>  include/tst_device.h                |   7 +
>  include/tst_uinput.h                |  48 ++++++
>  lib/tst_device.c                    |   8 +-
>  libs/libltpuinput/Makefile          |  12 ++
>  libs/libltpuinput/tst_uinput.c      | 143 ++++++++++++++++
>  runtest/uevent                      |   3 +
>  scenario_groups/default             |   1 +
>  testcases/kernel/uevents/.gitignore |   3 +
>  testcases/kernel/uevents/Makefile   |  10 ++
>  testcases/kernel/uevents/uevent.h   | 176 ++++++++++++++++++++
>  testcases/kernel/uevents/uevent01.c |  98 +++++++++++
>  testcases/kernel/uevents/uevent02.c | 143 ++++++++++++++++
>  testcases/kernel/uevents/uevent03.c | 248
> ++++++++++++++++++++++++++++
>  13 files changed, 896 insertions(+), 4 deletions(-)
>  create mode 100644 include/tst_uinput.h
>  create mode 100644 libs/libltpuinput/Makefile
>  create mode 100644 libs/libltpuinput/tst_uinput.c
>  create mode 100644 runtest/uevent
>  create mode 100644 testcases/kernel/uevents/.gitignore
>  create mode 100644 testcases/kernel/uevents/Makefile
>  create mode 100644 testcases/kernel/uevents/uevent.h
>  create mode 100644 testcases/kernel/uevents/uevent01.c
>  create mode 100644 testcases/kernel/uevents/uevent02.c
>  create mode 100644 testcases/kernel/uevents/uevent03.c
> 
> -- 
> 2.21.0
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [LTP] [PATCH v3 1/5] lib/tst_device: Export more functions.
  2019-08-26 15:57   ` Clemens Famulla-Conrad
@ 2019-09-02 13:02     ` Cyril Hrubis
  0 siblings, 0 replies; 13+ messages in thread
From: Cyril Hrubis @ 2019-09-02 13:02 UTC (permalink / raw)
  To: ltp

Hi!
> I just realized that copyright date might need an update
> and there are no function desc in tst_device.h.

Fixed both and pushed the patchset. Thanks a lot for the review.

-- 
Cyril Hrubis
chrubis@suse.cz

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-09-02 13:02 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-26 14:01 [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Cyril Hrubis
2019-08-26 14:01 ` [LTP] [PATCH v3 1/5] lib/tst_device: Export more functions Cyril Hrubis
2019-08-26 15:57   ` Clemens Famulla-Conrad
2019-09-02 13:02     ` Cyril Hrubis
2019-08-26 14:01 ` [LTP] [PATCH v3 2/5] kernel/uevent: Add uevent01 Cyril Hrubis
2019-08-26 15:57   ` Clemens Famulla-Conrad
2019-08-26 14:01 ` [LTP] [PATCH v3 3/5] kernel/uevent: Add uevent02 Cyril Hrubis
2019-08-26 15:55   ` Clemens Famulla-Conrad
2019-08-26 14:01 ` [LTP] [PATCH v3 4/5] libs/libltpuinput: Add uinput library Cyril Hrubis
2019-08-26 15:55   ` Clemens Famulla-Conrad
2019-08-26 14:01 ` [LTP] [PATCH v3 5/5] kernel/uevent: Add uevent03 Cyril Hrubis
2019-08-26 15:52   ` Clemens Famulla-Conrad
2019-08-26 15:59 ` [LTP] [PATCH v3 0/5] Add basic test for uevent netlink socket Clemens Famulla-Conrad

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.