• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Lloyd Pique <lpique@google.com>
3Date: Fri, 29 Jan 2021 17:24:56 -0800
4Subject: [PATCH 2/3] tests: Add demo real-world protocol logging
5
6Adds a real-world sample function for protocol message loging,
7duplicating the same output produced by the internal wl_closure_print.
8
9Signed-off-by: Lloyd Pique <lpique@google.com>
10
11diff --git a/tests/protocol-logger-test.c b/tests/protocol-logger-test.c
12index e409368..d0bca41 100644
13--- a/tests/protocol-logger-test.c
14+++ b/tests/protocol-logger-test.c
15@@ -29,10 +29,12 @@
16 #include <string.h>
17 #include <stdio.h>
18 #include <sys/un.h>
19+#include <time.h>
20 #include <unistd.h>
21
22 #include "wayland-client.h"
23 #include "wayland-server.h"
24+#include "wayland-util.h"
25 #include "test-runner.h"
26
27 /* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
28@@ -148,6 +150,116 @@ client_logger_func(void *user_data, enum wl_protocol_logger_client_type type,
29 	assert(msg->args_count == message->arguments_count);
30 }
31
32+// A slightly simplified version of  get_next_argument() from src/connection.c
33+static const char*
34+get_next_argument_type(const char *signature, char* type)
35+{
36+	for (; *signature; ++signature) {
37+		assert(strchr("iufsonah?", *signature) != NULL);
38+		switch (*signature) {
39+		case 'i':
40+		case 'u':
41+		case 'f':
42+		case 's':
43+		case 'o':
44+		case 'n':
45+		case 'a':
46+		case 'h':
47+			*type = *signature;
48+			return signature + 1;
49+		case '?':
50+			break;
51+
52+		}
53+	}
54+	*type = 0;
55+	return signature;
56+}
57+
58+// This duplicates what the internal wl_closure_print function does, and can be
59+// used as a starting point for a client or server that wants to log messages.
60+static void
61+client_log_to_stderr_demo(void *user_data,
62+			  enum wl_protocol_logger_client_type type,
63+			  const struct wl_protocol_logger_client_message *message) {
64+	int i;
65+	char arg_type;
66+	const char *signature = message->message->signature;
67+	const union wl_argument* args = message->arguments;
68+	struct wl_proxy* arg_proxy;
69+	const char* arg_class;
70+	struct timespec tp;
71+	unsigned int time;
72+
73+	clock_gettime(CLOCK_REALTIME, &tp);
74+	time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
75+
76+	// Note: server logger will be given message->resource, and should
77+	// use wl_resource_get_class and wl_resolurce_get_id.
78+	fprintf(stderr, "[%10.3f] %s%s@%u.%s(",
79+		time / 1000.0,
80+		(type == WL_PROTOCOL_LOGGER_CLIENT_REQUEST) ? " -> " : "",
81+		wl_proxy_get_class(message->proxy), wl_proxy_get_id(message->proxy),
82+		message->message->name);
83+
84+	for (i = 0; i < message->arguments_count; i++) {
85+		signature = get_next_argument_type(signature, &arg_type);
86+		if (i > 0)
87+			fprintf(stderr, ", ");
88+
89+		switch (arg_type) {
90+		case 'u':
91+			fprintf(stderr, "%u", args[i].u);
92+			break;
93+		case 'i':
94+			fprintf(stderr, "%d", args[i].i);
95+			break;
96+		case 'f':
97+			fprintf(stderr, "%f", wl_fixed_to_double(args[i].f));
98+			break;
99+		case 's':
100+			if (args[i].s)
101+				fprintf(stderr, "\"%s\"", args[i].s);
102+			else
103+				fprintf(stderr, "nil");
104+			break;
105+		case 'o':
106+			if (args[i].o) {
107+				// Note: server logger should instead cast to
108+				// wl_resource, and use wl_resource_get_class
109+				// and wl_resource_get_id.
110+				arg_proxy = (struct wl_proxy *)(args[i].o);
111+				arg_class = wl_proxy_get_class(arg_proxy);
112+
113+				fprintf(stderr, "%s@%u",
114+					arg_class ? arg_class : "[unknown]",
115+					wl_proxy_get_id(arg_proxy));
116+			} else {
117+				fprintf(stderr, "nil");
118+			}
119+			break;
120+		case 'n':
121+			fprintf(stderr, "new id %s@",
122+				  (message->message->types[i]) ?
123+				   message->message->types[i]->name :
124+				    "[unknown]");
125+			if (args[i].n != 0)
126+				fprintf(stderr, "%u", args[i].n);
127+			else
128+				fprintf(stderr, "nil");
129+			break;
130+		case 'a':
131+			fprintf(stderr, "array");
132+			break;
133+		case 'h':
134+			fprintf(stderr, "fd %d", args[i].h);
135+			break;
136+		}
137+	}
138+
139+	fprintf(stderr, ")\n");
140+}
141+
142 static void
143 callback_done(void *data, struct wl_callback *cb, uint32_t time)
144 {
145@@ -167,6 +279,7 @@ TEST(logger)
146 	struct client client = { 0 };
147 	struct wl_protocol_logger *logger;
148 	struct wl_protocol_logger_client *logger_client;
149+	struct wl_protocol_logger_client *logger_client_demo;
150
151 	require_xdg_runtime_dir();
152
153@@ -180,6 +293,8 @@ TEST(logger)
154 	client.display = wl_display_connect(socket);
155 	logger_client = wl_display_add_protocol_logger_client(
156 		client.display, client_logger_func, &client);
157+	logger_client_demo = wl_display_add_protocol_logger_client(
158+		client.display, client_log_to_stderr_demo, &client);
159 	client.cb = wl_display_sync(client.display);
160 	wl_callback_add_listener(client.cb, &callback_listener, NULL);
161 	wl_display_flush(client.display);
162@@ -193,6 +308,7 @@ TEST(logger)
163 	wl_display_disconnect(client.display);
164
165 	wl_protocol_logger_client_destroy(logger_client);
166+	wl_protocol_logger_client_destroy(logger_client_demo);
167 	wl_client_destroy(compositor.client);
168 	wl_protocol_logger_destroy(logger);
169 	wl_display_destroy(compositor.display);
170