[LTP] [PATCH v2 16/31] testcases: sysfs: Add sys_wakeup01

Cyril Hrubis <[email protected]>
Newsgroups it.linux.lists.ltp
Message-ID <[email protected]>
A test for /sys/class/wakeup/*/* files.

Signed-off-by: Cyril Hrubis <[email protected]>
---
 runtest/sysfs                                 |   1 +
 .../kernel/sysfs/class/wakeup/.gitignore      |   1 +
 testcases/kernel/sysfs/class/wakeup/Makefile  |   7 ++
 .../kernel/sysfs/class/wakeup/sys_wakeup01.c  | 118 ++++++++++++++++++
 4 files changed, 127 insertions(+)
 create mode 100644 testcases/kernel/sysfs/class/wakeup/.gitignore
 create mode 100644 testcases/kernel/sysfs/class/wakeup/Makefile
 create mode 100644 testcases/kernel/sysfs/class/wakeup/sys_wakeup01.c

diff --git a/runtest/sysfs b/runtest/sysfs
index f515c4c1e..b8d003228 100644
--- a/runtest/sysfs
+++ b/runtest/sysfs
@@ -12,3 +12,4 @@ sys_ata01 sys_ata01
 sys_bdi01 sys_bdi01
 sys_hwmon01 sys_hwmon01
 sys_leds01 sys_leds01
+sys_wakeup01 sys_wakeup01
diff --git a/testcases/kernel/sysfs/class/wakeup/.gitignore b/testcases/kernel/sysfs/class/wakeup/.gitignore
new file mode 100644
index 000000000..16d0375cd
--- /dev/null
+++ b/testcases/kernel/sysfs/class/wakeup/.gitignore
@@ -0,0 +1 @@
+/sys_wakeup01
diff --git a/testcases/kernel/sysfs/class/wakeup/Makefile b/testcases/kernel/sysfs/class/wakeup/Makefile
new file mode 100644
index 000000000..034038061
--- /dev/null
+++ b/testcases/kernel/sysfs/class/wakeup/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2026 Cyril Hrubis <[email protected]>
+
+top_srcdir		?= ../../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/sysfs/class/wakeup/sys_wakeup01.c b/testcases/kernel/sysfs/class/wakeup/sys_wakeup01.c
new file mode 100644
index 000000000..37e5ceafc
--- /dev/null
+++ b/testcases/kernel/sysfs/class/wakeup/sys_wakeup01.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Cyril Hrubis <[email protected]>
+ */
+
+/*\
+ * Sanity checks for the wakeup source statistics exported under
+ * /sys/class/wakeup/wakeupN/.
+ *
+ * For every wakeup source the test verifies that:
+ *
+ * - name is a non-empty string
+ * - active_count, active_time_ms, event_count, expire_count, last_change_ms,
+ *   max_time_ms, prevent_suspend_time_ms, total_time_ms and wakeup_count are
+ *   all non-negative
+ * - active_time_ms <= total_time_ms (currently active time is part of the
+ *   accumulated total)
+ * - max_time_ms <= total_time_ms (the longest single event cannot exceed the
+ *   accumulated total)
+ *
+ * The test skips with TCONF when no wakeup source is present.
+ */
+
+#include <string.h>
+#include <limits.h>
+#include <dirent.h>
+#include "tst_test.h"
+#include "tst_sysfs_assert.h"
+
+#define WAKEUP "/sys/class/wakeup"
+
+/*
+ * active_count/event_count/wakeup_count/expire_count are exported by the
+ * kernel as "unsigned long" (see drivers/base/power/wakeup_stats.c), hence
+ * the RANGEUU (unsigned long long bounds) variant is used for these: it
+ * lets us use the real ULONG_MAX.
+ */
+static const char *const count_attrs[] = {
+	"active_count",
+	"event_count",
+	"expire_count",
+	"wakeup_count",
+};
+
+/*
+ * active_time_ms/total_time_ms/max_time_ms/last_change_ms/
+ * prevent_suspend_time_ms are exported by the kernel as a signed 64bit
+ * ktime_t converted to milliseconds (see drivers/base/power/wakeup_stats.c),
+ * i.e. their real ceiling is LLONG_MAX regardless of the architecture. On a
+ * 32bit test build "long" is only 32bit (~24.8 days worth of ms), so plain
+ * LONG_MAX would be too tight and could false-fail on a long-uptime system.
+ */
+static const char *const time_ms_attrs[] = {
+	"active_time_ms",
+	"last_change_ms",
+	"max_time_ms",
+	"prevent_suspend_time_ms",
+	"total_time_ms",
+};
+
+static void check_wakeup(const char *dev)
+{
+	char name[128] = "";
+	unsigned int i;
+
+	tst_res(TINFO, "Checking %s", dev);
+
+	if (!TST_SYSFS_READ_STR(name, sizeof(name), WAKEUP "/%s/name", dev)) {
+		tst_res(TCONF, "%s vanished before it could be checked", dev);
+		return;
+	}
+
+	if (name[0] != '\0')
+		tst_res(TPASS, "%s: name = '%s'", dev, name);
+	else
+		tst_res(TFAIL, "%s: name is empty", dev);
+
+	for (i = 0; i < ARRAY_SIZE(count_attrs); i++) {
+		TST_SYSFS_ASSERT_RANGEUU(0, ULONG_MAX, WAKEUP "/%s/%s", dev,
+					 count_attrs[i]);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(time_ms_attrs); i++) {
+		TST_SYSFS_ASSERT_RANGELL(0, LLONG_MAX, WAKEUP "/%s/%s", dev,
+					 time_ms_attrs[i]);
+	}
+
+	TST_SYSFS_ASSERT_LE_SUFFIX("active_time_ms", "total_time_ms",
+				   WAKEUP "/%s/", dev);
+	TST_SYSFS_ASSERT_LE_SUFFIX("max_time_ms", "total_time_ms",
+				   WAKEUP "/%s/", dev);
+}
+
+static void do_test(void)
+{
+	DIR *d;
+	struct dirent *ent;
+	int found = 0;
+
+	d = SAFE_OPENDIR(WAKEUP);
+
+	while ((ent = SAFE_READDIR(d))) {
+		if (strncmp(ent->d_name, "wakeup", 6))
+			continue;
+
+		found = 1;
+		check_wakeup(ent->d_name);
+	}
+
+	SAFE_CLOSEDIR(d);
+
+	if (!found)
+		tst_res(TCONF, "No wakeup source found");
+}
+
+static struct tst_test test = {
+	.test_all = do_test,
+};
-- 
2.54.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.