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