From d5168b8eb0d881a0a6029c0b348a739147317238 Mon Sep 17 00:00:00 2001
From: Marius Vlad <marius.vlad@collabora.com>
Date: Mon, 29 May 2023 16:30:02 +0300
Subject: [PATCH] libweston/weston-log: Add a iterator helper for debug scope

This adds three new helpers: one to iterate over all debug scopes
created/added and other two are for simpler getters for the scope name
and the description.

Included with this change is also a simple test to retrieve them.

This is an alternative to using the debug scope list advertised when
using the weston-debug private extension. libweston users can use this
directly to know which scopes they can subscribe to, and there's no need
to have a client implementation for the weston-debug protocol.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
---
 include/libweston/weston-log.h    | 10 ++++
 libweston/weston-log.c            | 63 +++++++++++++++++++++++
 tests/iterate-debug-scopes-test.c | 84 +++++++++++++++++++++++++++++++
 tests/meson.build                 |  6 +++
 4 files changed, 163 insertions(+)
 create mode 100644 tests/iterate-debug-scopes-test.c

diff --git a/include/libweston/weston-log.h b/include/libweston/weston-log.h
index aeb7768b..70f41675 100644
--- a/include/libweston/weston-log.h
+++ b/include/libweston/weston-log.h
@@ -134,6 +134,16 @@ weston_log_subscription_iterate(struct weston_log_scope *scope,
 void
 weston_log_flight_recorder_display_buffer(FILE *file);
 
+const char *
+weston_log_scope_get_description(struct weston_log_scope *scope);
+
+const char *
+weston_log_scope_get_name(struct weston_log_scope *scope);
+
+struct weston_log_scope *
+weston_log_scopes_iterate(struct weston_log_context *log_ctx,
+                          struct weston_log_scope *nscope);
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/libweston/weston-log.c b/libweston/weston-log.c
index 276fde26..8b4c78a5 100644
--- a/libweston/weston-log.c
+++ b/libweston/weston-log.c
@@ -1009,3 +1009,66 @@ weston_log_subscription_iterate(struct weston_log_scope *scope,
 
 	return container_of(node, struct weston_log_subscription, source_link);
 }
+
+/** Iterate over all debug scopes added to a weston_log_context
+ *
+ * @param log_ctx the log context
+ * @param nscope the iterator, use NULL to start from the head of the list
+ * @returns the next log scope from list added to weston_log_ctx
+ *
+ * Note that that \c nscope needs to be NULL-initialized before calling
+ * this function.
+ *
+ * This helper can be used by libweston users to grab all the debug scopes
+ * created. This would be an alternative to using weston-debug private
+ * extension.
+ *
+ */
+WL_EXPORT struct weston_log_scope *
+weston_log_scopes_iterate(struct weston_log_context *log_ctx,
+                          struct weston_log_scope *nscope)
+{
+        struct wl_list *list;
+        struct wl_list *node;
+
+        assert(log_ctx);
+
+        list = &log_ctx->scope_list;
+
+        if (nscope) {
+                node = nscope->compositor_link.next;
+        } else {
+                node = list->next;
+        }
+
+	assert(node);
+	assert(!nscope || node != &nscope->compositor_link);
+
+        if (node == list)
+                return NULL;
+
+        return container_of(node, struct weston_log_scope, compositor_link);
+}
+
+/** Helper to retrieve, in human readable form,  the name of a log scope
+ *
+ * @param scope the scope in question
+ * @returns the name of the scope as a pointer to a string
+ */
+WL_EXPORT const char *
+weston_log_scope_get_name(struct weston_log_scope *scope)
+{
+        return scope->name;
+}
+
+/** Helper to retreive, in human reable form, the description of a log scope
+ *
+ * @param scope the scope in question
+ * @returns the description of the scope as pointer to a string
+ *
+ */
+WL_EXPORT const char *
+weston_log_scope_get_description(struct weston_log_scope *scope)
+{
+        return scope->desc;
+}
diff --git a/tests/iterate-debug-scopes-test.c b/tests/iterate-debug-scopes-test.c
new file mode 100644
index 00000000..82c6c5c8
--- /dev/null
+++ b/tests/iterate-debug-scopes-test.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2023 Collabora, 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 "config.h"
+
+#include <unistd.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libweston/weston-log.h>
+#include "weston-test-client-helper.h"
+#include "weston-test-fixture-compositor.h"
+
+
+static enum test_result_code
+fixture_setup(struct weston_test_harness *harness)
+{
+       struct compositor_setup setup;
+
+       compositor_setup_defaults(&setup);
+       setup.shell = SHELL_TEST_DESKTOP;
+
+       return weston_test_harness_execute_as_plugin(harness, &setup);
+}
+
+DECLARE_FIXTURE_SETUP(fixture_setup);
+
+static void
+iterate_debug_scopes(struct weston_compositor *compositor)
+{
+	struct weston_log_scope *nscope = NULL;
+	const char *test_harness_scope = "test-harness-plugin";
+	bool found_test_harness_debug_scope = false;
+	struct weston_log_context *log_ctx = compositor->weston_log_ctx;
+
+	weston_log("Printing available debug scopes:\n");
+
+	while ((nscope = weston_log_scopes_iterate(log_ctx, nscope))) {
+		const char *scope_name;
+		const char *desc_name;
+
+		scope_name = weston_log_scope_get_name(nscope);
+		assert(scope_name);
+
+		desc_name = weston_log_scope_get_description(nscope);
+		assert(desc_name);
+
+		weston_log("\tscope name: %s, desc: %s\n", scope_name, desc_name);
+
+		if (strcmp(test_harness_scope, scope_name) == 0)
+			found_test_harness_debug_scope = true;
+	}
+	weston_log("\n");
+
+	assert(found_test_harness_debug_scope);
+}
+
+PLUGIN_TEST(iterate_default_debug_scopes)
+{
+       iterate_debug_scopes(compositor);
+}
diff --git a/tests/meson.build b/tests/meson.build
index d8e96e77..e52ff5a6 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -224,6 +224,12 @@ tests = [
 		],
 		'dep_objs': [ dep_lib_desktop ]
 	},
+	{	'name': 'iterate-debug-scopes',
+		'sources': [
+		  'iterate-debug-scopes-test.c',
+		],
+		'dep_objs': [ dep_libweston_public ]
+	},
 ]
 
 tests_standalone = [
-- 
2.40.1

