diff mbox series

[v2,3/3] libtracefs: Unit test for tracefs_instance_reset()

Message ID 20230426041124.69544-4-tz.stoyanov@gmail.com (mailing list archive)
State Accepted
Commit b1b234e854c5e6c87e7bbff4ff1e4814d8014671
Headers show
Series libtracefs: Introduce new API to reset ftrace instance | expand

Commit Message

Tzvetomir Stoyanov (VMware) April 26, 2023, 4:11 a.m. UTC
The logic of the tracefs_instance_reset() is complex and should be
covered by the unit tests of the tracefs library.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 utest/tracefs-utest.c | 183 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 183 insertions(+)

Comments

Steven Rostedt May 29, 2023, 12:05 p.m. UTC | #1
On Wed, 26 Apr 2023 07:11:24 +0300
"Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote:

> +static void test_instance_reset(void)
> +{
> +	struct tracefs_instance *instance = NULL;
> +	const char *name = get_rand_str();
> +
> +	CU_TEST(tracefs_instance_exists(name) == false);
> +	instance = tracefs_instance_create(name);
> +	CU_TEST(instance != NULL);
> +
> +	CU_TEST(test_instance_check_default_state(instance) == true);
> +
> +	CU_TEST(tracefs_tracer_set(instance, TRACEFS_TRACER_HWLAT) == 0);
> +	CU_TEST(tracefs_event_enable(instance, "bridge", "fdb_delete") == 0);

Was there a reason why you picked HWLAT tracer and the fdb_delete trace
event? Neither exist in my test machine setup, so this test
automatically fails.

-- Steve


> +	CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_pid", "5") > 0);
> +	CU_TEST(tracefs_instance_file_write(instance, "trace_clock", "global") > 0);
> +	CU_TEST(tracefs_instance_file_write(instance, "set_event_pid", "5") > 0);
> +	CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_filter",
> +						      "schedule:stacktrace") > 0);
> +	CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_notrace",
> +						      "schedule:stacktrace") > 0);
> +	CU_TEST(tracefs_instance_file_write(instance, "tracing_cpumask", "0f") > 0);
> +	CU_TEST(tracefs_instance_file_write(instance, "events/syscalls/sys_exit_read/trigger",
> +						      "enable_event:kmem:kmalloc:1") > 0);
> +	CU_TEST(tracefs_instance_file_write(instance, "events/bridge/fdb_delete/filter",
> +						      "common_pid == 5") > 0);
> +
> +	CU_TEST(test_instance_check_default_state(instance) == false);
> +
> +	tracefs_instance_reset(instance);
> +	CU_TEST(test_instance_check_default_state(instance) == true);
> +
> +	CU_TEST(tracefs_instance_destroy(instance) == 0);
> +	tracefs_instance_free(instance);
> +}
> +
Tzvetomir Stoyanov (VMware) May 30, 2023, 8:19 a.m. UTC | #2
On Mon, May 29, 2023 at 3:05 PM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Wed, 26 Apr 2023 07:11:24 +0300
> "Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com> wrote:
>
> > +static void test_instance_reset(void)
> > +{
> > +     struct tracefs_instance *instance = NULL;
> > +     const char *name = get_rand_str();
> > +
> > +     CU_TEST(tracefs_instance_exists(name) == false);
> > +     instance = tracefs_instance_create(name);
> > +     CU_TEST(instance != NULL);
> > +
> > +     CU_TEST(test_instance_check_default_state(instance) == true);
> > +
> > +     CU_TEST(tracefs_tracer_set(instance, TRACEFS_TRACER_HWLAT) == 0);
> > +     CU_TEST(tracefs_event_enable(instance, "bridge", "fdb_delete") == 0);
>
> Was there a reason why you picked HWLAT tracer and the fdb_delete trace
> event? Neither exist in my test machine setup, so this test
> automatically fails.
>

Hi Steve,
The only reason to choose them is not to generate many events during
the test, as the test checks the ftrace configuration and not the
generated events. I didn't realize that the tracer and events may not
exist in the system. I noticed your commit, thanks for fixing that!

> -- Steve
>
>
> > +     CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_pid", "5") > 0);
> > +     CU_TEST(tracefs_instance_file_write(instance, "trace_clock", "global") > 0);
> > +     CU_TEST(tracefs_instance_file_write(instance, "set_event_pid", "5") > 0);
> > +     CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_filter",
> > +                                                   "schedule:stacktrace") > 0);
> > +     CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_notrace",
> > +                                                   "schedule:stacktrace") > 0);
> > +     CU_TEST(tracefs_instance_file_write(instance, "tracing_cpumask", "0f") > 0);
> > +     CU_TEST(tracefs_instance_file_write(instance, "events/syscalls/sys_exit_read/trigger",
> > +                                                   "enable_event:kmem:kmalloc:1") > 0);
> > +     CU_TEST(tracefs_instance_file_write(instance, "events/bridge/fdb_delete/filter",
> > +                                                   "common_pid == 5") > 0);
> > +
> > +     CU_TEST(test_instance_check_default_state(instance) == false);
> > +
> > +     tracefs_instance_reset(instance);
> > +     CU_TEST(test_instance_check_default_state(instance) == true);
> > +
> > +     CU_TEST(tracefs_instance_destroy(instance) == 0);
> > +     tracefs_instance_free(instance);
> > +}
> > +
diff mbox series

Patch

diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c
index e0e3c07..47f65cb 100644
--- a/utest/tracefs-utest.c
+++ b/utest/tracefs-utest.c
@@ -1618,6 +1618,187 @@  static void test_instance_file(void)
 	free(inst_dir);
 }
 
+static bool test_check_file_content(struct tracefs_instance *instance, char *file,
+				    char *content, bool full_match, bool ignore_comments)
+{
+	char *save = NULL;
+	char *buf, *line;
+	bool ret = false;
+	int len;
+
+	if (!tracefs_file_exists(instance, file))
+		return false;
+
+	buf = tracefs_instance_file_read(instance, file, NULL);
+	if (strlen(content) == 0) {
+		/* check for empty file */
+		if (!buf)
+			return true;
+		if (!ignore_comments) {
+			if (strlen(buf) > 0)
+				goto out;
+		} else {
+			line = strtok_r(buf, "\n", &save);
+			while (line) {
+				if (line[0] != '#')
+					goto out;
+				line = strtok_r(NULL, "\n", &save);
+			}
+		}
+	} else {
+		if (!buf || strlen(buf) < 1)
+			return false;
+		if (full_match) {
+			/* strip the newline */
+			len = strlen(buf) - 1;
+			while (buf[len] == '\n' || buf[len] == '\r') {
+				buf[len] = '\0';
+				len = strlen(buf) - 1;
+				if (len < 0)
+					goto out;
+			}
+			if (strcmp(buf, content))
+				goto out;
+		} else {
+			if (!strstr(buf, content))
+				goto out;
+		}
+	}
+
+	ret = true;
+out:
+	free(buf);
+	return ret;
+}
+
+static bool test_check_event_file_content(struct tracefs_instance *instance,
+					  char *system, char *event, char *file,
+					  char *content, bool full_match, bool ignore_comments)
+{
+	char *efile;
+	int ret;
+
+	ret = asprintf(&efile, "events/%s/%s/%s", system, event, file);
+	if (ret <= 0)
+		return false;
+	ret = test_check_file_content(instance, efile, content, full_match, ignore_comments);
+	free(efile);
+	return ret;
+}
+
+static bool check_cpu_mask(struct tracefs_instance *instance)
+{
+	int cpus = sysconf(_SC_NPROCESSORS_CONF);
+	int fullwords = (cpus - 1) / 32;
+	int bits = (cpus - 1) % 32 + 1;
+	int len = (fullwords + 1) * 9;
+	char buf[len + 1];
+
+	buf[0] = '\0';
+	sprintf(buf, "%x", (unsigned int)((1ULL << bits) - 1));
+	while (fullwords-- > 0)
+		strcat(buf, ",ffffffff");
+
+	return test_check_file_content(instance, "tracing_cpumask", buf, true, false);
+}
+
+static bool test_instance_check_default_state(struct tracefs_instance *instance)
+{
+	char **systems;
+	char **events;
+	int i, j;
+	int ok;
+
+	if (tracefs_trace_is_on(instance) != 1)
+		return false;
+	if (!test_check_file_content(instance, "current_tracer", "nop", true, false))
+		return false;
+	if (!test_check_file_content(instance, "events/enable", "0", true, false))
+		return false;
+	if (!test_check_file_content(instance, "set_ftrace_pid", "no pid", true, false))
+		return false;
+	if (!test_check_file_content(instance, "trace", "", true, true))
+		return false;
+	if (!test_check_file_content(instance, "error_log", "", true, false))
+		return false;
+	if (!test_check_file_content(instance, "trace_clock", "[local]", false, false))
+		return false;
+	if (!test_check_file_content(instance, "set_event_pid", "", true, false))
+		return false;
+	if (!test_check_file_content(instance, "tracing_max_latency", "0", true, false))
+		return false;
+	if (!test_check_file_content(instance, "set_ftrace_filter", "", true, true))
+		return false;
+	if (!test_check_file_content(instance, "set_ftrace_notrace", "", true, true))
+		return false;
+	if (!check_cpu_mask(instance))
+		return false;
+
+	ok = 1;
+	systems = tracefs_event_systems(NULL);
+	if (systems) {
+		for (i = 0; systems[i]; i++) {
+			events = tracefs_system_events(NULL, systems[i]);
+			if (!events)
+				continue;
+			for (j = 0; events[j]; j++) {
+				if (!test_check_event_file_content(instance, systems[i], events[j],
+								    "enable", "0", true, false))
+					break;
+				if (!test_check_event_file_content(instance, systems[i], events[j],
+								    "filter", "none", true, false))
+					break;
+				if (!test_check_event_file_content(instance, systems[i], events[j],
+								    "trigger", "", true, true))
+					break;
+			}
+			if (events[j])
+				ok = 0;
+			tracefs_list_free(events);
+			if (!ok)
+				return false;
+		}
+		tracefs_list_free(systems);
+	}
+
+	return true;
+}
+
+static void test_instance_reset(void)
+{
+	struct tracefs_instance *instance = NULL;
+	const char *name = get_rand_str();
+
+	CU_TEST(tracefs_instance_exists(name) == false);
+	instance = tracefs_instance_create(name);
+	CU_TEST(instance != NULL);
+
+	CU_TEST(test_instance_check_default_state(instance) == true);
+
+	CU_TEST(tracefs_tracer_set(instance, TRACEFS_TRACER_HWLAT) == 0);
+	CU_TEST(tracefs_event_enable(instance, "bridge", "fdb_delete") == 0);
+	CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_pid", "5") > 0);
+	CU_TEST(tracefs_instance_file_write(instance, "trace_clock", "global") > 0);
+	CU_TEST(tracefs_instance_file_write(instance, "set_event_pid", "5") > 0);
+	CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_filter",
+						      "schedule:stacktrace") > 0);
+	CU_TEST(tracefs_instance_file_write(instance, "set_ftrace_notrace",
+						      "schedule:stacktrace") > 0);
+	CU_TEST(tracefs_instance_file_write(instance, "tracing_cpumask", "0f") > 0);
+	CU_TEST(tracefs_instance_file_write(instance, "events/syscalls/sys_exit_read/trigger",
+						      "enable_event:kmem:kmalloc:1") > 0);
+	CU_TEST(tracefs_instance_file_write(instance, "events/bridge/fdb_delete/filter",
+						      "common_pid == 5") > 0);
+
+	CU_TEST(test_instance_check_default_state(instance) == false);
+
+	tracefs_instance_reset(instance);
+	CU_TEST(test_instance_check_default_state(instance) == true);
+
+	CU_TEST(tracefs_instance_destroy(instance) == 0);
+	tracefs_instance_free(instance);
+}
+
 static bool check_fd_name(int fd, const char *dir, const char *name)
 {
 	char link[PATH_MAX + 1];
@@ -2354,6 +2535,8 @@  void test_tracefs_lib(void)
 		    test_file_fd);
 	CU_add_test(suite, "instance file descriptor",
 		    test_instance_file);
+	CU_add_test(suite, "instance reset",
+		    test_instance_reset);
 	CU_add_test(suite, "systems and events APIs",
 		    test_system_event);
 	CU_add_test(suite, "tracefs_iterate_raw_events API",