blob: b262ec0bd55d3c3e5c2ef7e3855bb01a8cf211c4 [file] [log] [blame]
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lloyd Pique <lpique@google.com>
Date: Fri, 29 Jan 2021 17:24:56 -0800
Subject: [PATCH 2/3] tests: Add demo real-world protocol logging
Adds a real-world sample function for protocol message loging,
duplicating the same output produced by the internal wl_closure_print.
Signed-off-by: Lloyd Pique <lpique@google.com>
diff --git a/tests/protocol-logger-test.c b/tests/protocol-logger-test.c
index e409368..d0bca41 100644
--- a/tests/protocol-logger-test.c
+++ b/tests/protocol-logger-test.c
@@ -29,10 +29,12 @@
#include <string.h>
#include <stdio.h>
#include <sys/un.h>
+#include <time.h>
#include <unistd.h>
#include "wayland-client.h"
#include "wayland-server.h"
+#include "wayland-util.h"
#include "test-runner.h"
/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
@@ -148,6 +150,116 @@ client_logger_func(void *user_data, enum wl_protocol_logger_client_type type,
assert(msg->args_count == message->arguments_count);
}
+// A slightly simplified version of get_next_argument() from src/connection.c
+static const char*
+get_next_argument_type(const char *signature, char* type)
+{
+ for (; *signature; ++signature) {
+ assert(strchr("iufsonah?", *signature) != NULL);
+ switch (*signature) {
+ case 'i':
+ case 'u':
+ case 'f':
+ case 's':
+ case 'o':
+ case 'n':
+ case 'a':
+ case 'h':
+ *type = *signature;
+ return signature + 1;
+ case '?':
+ break;
+
+ }
+ }
+ *type = 0;
+ return signature;
+}
+
+// This duplicates what the internal wl_closure_print function does, and can be
+// used as a starting point for a client or server that wants to log messages.
+static void
+client_log_to_stderr_demo(void *user_data,
+ enum wl_protocol_logger_client_type type,
+ const struct wl_protocol_logger_client_message *message) {
+ int i;
+ char arg_type;
+ const char *signature = message->message->signature;
+ const union wl_argument* args = message->arguments;
+ struct wl_proxy* arg_proxy;
+ const char* arg_class;
+ struct timespec tp;
+ unsigned int time;
+
+ clock_gettime(CLOCK_REALTIME, &tp);
+ time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
+
+ // Note: server logger will be given message->resource, and should
+ // use wl_resource_get_class and wl_resolurce_get_id.
+ fprintf(stderr, "[%10.3f] %s%s@%u.%s(",
+ time / 1000.0,
+ (type == WL_PROTOCOL_LOGGER_CLIENT_REQUEST) ? " -> " : "",
+ wl_proxy_get_class(message->proxy), wl_proxy_get_id(message->proxy),
+ message->message->name);
+
+ for (i = 0; i < message->arguments_count; i++) {
+ signature = get_next_argument_type(signature, &arg_type);
+ if (i > 0)
+ fprintf(stderr, ", ");
+
+ switch (arg_type) {
+ case 'u':
+ fprintf(stderr, "%u", args[i].u);
+ break;
+ case 'i':
+ fprintf(stderr, "%d", args[i].i);
+ break;
+ case 'f':
+ fprintf(stderr, "%f", wl_fixed_to_double(args[i].f));
+ break;
+ case 's':
+ if (args[i].s)
+ fprintf(stderr, "\"%s\"", args[i].s);
+ else
+ fprintf(stderr, "nil");
+ break;
+ case 'o':
+ if (args[i].o) {
+ // Note: server logger should instead cast to
+ // wl_resource, and use wl_resource_get_class
+ // and wl_resource_get_id.
+ arg_proxy = (struct wl_proxy *)(args[i].o);
+ arg_class = wl_proxy_get_class(arg_proxy);
+
+ fprintf(stderr, "%s@%u",
+ arg_class ? arg_class : "[unknown]",
+ wl_proxy_get_id(arg_proxy));
+ } else {
+ fprintf(stderr, "nil");
+ }
+ break;
+ case 'n':
+ fprintf(stderr, "new id %s@",
+ (message->message->types[i]) ?
+ message->message->types[i]->name :
+ "[unknown]");
+ if (args[i].n != 0)
+ fprintf(stderr, "%u", args[i].n);
+ else
+ fprintf(stderr, "nil");
+ break;
+ case 'a':
+ fprintf(stderr, "array");
+ break;
+ case 'h':
+ fprintf(stderr, "fd %d", args[i].h);
+ break;
+ }
+ }
+
+ fprintf(stderr, ")\n");
+}
+
static void
callback_done(void *data, struct wl_callback *cb, uint32_t time)
{
@@ -167,6 +279,7 @@ TEST(logger)
struct client client = { 0 };
struct wl_protocol_logger *logger;
struct wl_protocol_logger_client *logger_client;
+ struct wl_protocol_logger_client *logger_client_demo;
require_xdg_runtime_dir();
@@ -180,6 +293,8 @@ TEST(logger)
client.display = wl_display_connect(socket);
logger_client = wl_display_add_protocol_logger_client(
client.display, client_logger_func, &client);
+ logger_client_demo = wl_display_add_protocol_logger_client(
+ client.display, client_log_to_stderr_demo, &client);
client.cb = wl_display_sync(client.display);
wl_callback_add_listener(client.cb, &callback_listener, NULL);
wl_display_flush(client.display);
@@ -193,6 +308,7 @@ TEST(logger)
wl_display_disconnect(client.display);
wl_protocol_logger_client_destroy(logger_client);
+ wl_protocol_logger_client_destroy(logger_client_demo);
wl_client_destroy(compositor.client);
wl_protocol_logger_destroy(logger);
wl_display_destroy(compositor.display);