1*84e872a0SLloyd PiqueFrom 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2*84e872a0SLloyd PiqueFrom: Lloyd Pique <[email protected]> 3*84e872a0SLloyd PiqueDate: Fri, 11 Mar 2022 17:57:37 -0800 4*84e872a0SLloyd PiqueSubject: [PATCH 3/6] protocol-logger-test: Demonstrate logging 5*84e872a0SLloyd Pique 6*84e872a0SLloyd PiqueClient message observers 3/6 7*84e872a0SLloyd Pique 8*84e872a0SLloyd PiqueAdds code demonstrating how to replicate the output produced by the internal 9*84e872a0SLloyd Piquewl_closure_print() using the client message observer interface. 10*84e872a0SLloyd Pique 11*84e872a0SLloyd PiqueIf you run protocol-logger-test with "WAYLAND_DEBUG=client", you can see the 12*84e872a0SLloyd Piqueclient messages logged to stderr twice, with the same strings. 13*84e872a0SLloyd Pique 14*84e872a0SLloyd PiqueSigned-off-by: Lloyd Pique <[email protected]> 15*84e872a0SLloyd Pique 16*84e872a0SLloyd Piquediff --git a/tests/protocol-logger-test.c b/tests/protocol-logger-test.c 17*84e872a0SLloyd Piqueindex 3b9dc3e..082f055 100644 18*84e872a0SLloyd Pique--- a/tests/protocol-logger-test.c 19*84e872a0SLloyd Pique+++ b/tests/protocol-logger-test.c 20*84e872a0SLloyd Pique@@ -80,6 +80,7 @@ struct client { 21*84e872a0SLloyd Pique struct wl_display *display; 22*84e872a0SLloyd Pique struct wl_callback *cb; 23*84e872a0SLloyd Pique struct wl_client_observer *sequence_observer; 24*84e872a0SLloyd Pique+ struct wl_client_observer *stderr_logger; 25*84e872a0SLloyd Pique 26*84e872a0SLloyd Pique struct expected_client_message *expected_msg; 27*84e872a0SLloyd Pique int expected_msg_count; 28*84e872a0SLloyd Pique@@ -190,6 +191,130 @@ client_sequence_observer_func( 29*84e872a0SLloyd Pique "arg count mismatch: %s", details_msg); 30*84e872a0SLloyd Pique } 31*84e872a0SLloyd Pique 32*84e872a0SLloyd Pique+// A slightly simplified version of get_next_argument() from src/connection.c 33*84e872a0SLloyd Pique+static const char * 34*84e872a0SLloyd Pique+get_next_argument_type(const char *signature, char *type) 35*84e872a0SLloyd Pique+{ 36*84e872a0SLloyd Pique+ for (; *signature; ++signature) { 37*84e872a0SLloyd Pique+ assert(strchr("iufsonah?", *signature) != NULL); 38*84e872a0SLloyd Pique+ switch (*signature) { 39*84e872a0SLloyd Pique+ case 'i': 40*84e872a0SLloyd Pique+ case 'u': 41*84e872a0SLloyd Pique+ case 'f': 42*84e872a0SLloyd Pique+ case 's': 43*84e872a0SLloyd Pique+ case 'o': 44*84e872a0SLloyd Pique+ case 'n': 45*84e872a0SLloyd Pique+ case 'a': 46*84e872a0SLloyd Pique+ case 'h': 47*84e872a0SLloyd Pique+ *type = *signature; 48*84e872a0SLloyd Pique+ return signature + 1; 49*84e872a0SLloyd Pique+ case '?': 50*84e872a0SLloyd Pique+ break; 51*84e872a0SLloyd Pique+ } 52*84e872a0SLloyd Pique+ } 53*84e872a0SLloyd Pique+ *type = 0; 54*84e872a0SLloyd Pique+ return signature; 55*84e872a0SLloyd Pique+} 56*84e872a0SLloyd Pique+ 57*84e872a0SLloyd Pique+// This duplicates what the internal wl_closure_print function does, and can be 58*84e872a0SLloyd Pique+// used as a starting point for a client or server that wants to log messages. 59*84e872a0SLloyd Pique+static void 60*84e872a0SLloyd Pique+client_log_to_stderr_demo(void *user_data, enum wl_client_message_type type, 61*84e872a0SLloyd Pique+ const struct wl_client_observed_message *message) 62*84e872a0SLloyd Pique+{ 63*84e872a0SLloyd Pique+ int i; 64*84e872a0SLloyd Pique+ char arg_type; 65*84e872a0SLloyd Pique+ const char *signature = message->message->signature; 66*84e872a0SLloyd Pique+ const union wl_argument *args = message->arguments; 67*84e872a0SLloyd Pique+ struct wl_proxy *arg_proxy; 68*84e872a0SLloyd Pique+ const char *arg_class; 69*84e872a0SLloyd Pique+ struct timespec tp; 70*84e872a0SLloyd Pique+ unsigned long long time; 71*84e872a0SLloyd Pique+ FILE *f; 72*84e872a0SLloyd Pique+ char *buffer; 73*84e872a0SLloyd Pique+ size_t buffer_length; 74*84e872a0SLloyd Pique+ 75*84e872a0SLloyd Pique+ f = open_memstream(&buffer, &buffer_length); 76*84e872a0SLloyd Pique+ if (f == NULL) 77*84e872a0SLloyd Pique+ return; 78*84e872a0SLloyd Pique+ 79*84e872a0SLloyd Pique+ clock_gettime(CLOCK_REALTIME, &tp); 80*84e872a0SLloyd Pique+ time = (tp.tv_sec * 1000000LL) + (tp.tv_nsec / 1000); 81*84e872a0SLloyd Pique+ 82*84e872a0SLloyd Pique+ // Note: server logger will be given message->resource, and should 83*84e872a0SLloyd Pique+ // use wl_resource_get_class and wl_resolurce_get_id. 84*84e872a0SLloyd Pique+ fprintf(f, "[%7llu.%03llu] %s%s%s%s%s@%u.%s(", time / 1000, time % 1000, 85*84e872a0SLloyd Pique+ (message->discarded_reason_str ? "discarded[" : ""), 86*84e872a0SLloyd Pique+ (message->discarded_reason_str ? message->discarded_reason_str 87*84e872a0SLloyd Pique+ : ""), 88*84e872a0SLloyd Pique+ (message->discarded_reason_str ? "] " : ""), 89*84e872a0SLloyd Pique+ (type == WL_CLIENT_MESSAGE_REQUEST) ? " -> " : "", 90*84e872a0SLloyd Pique+ wl_proxy_get_class(message->proxy), 91*84e872a0SLloyd Pique+ wl_proxy_get_id(message->proxy), message->message->name); 92*84e872a0SLloyd Pique+ 93*84e872a0SLloyd Pique+ for (i = 0; i < message->arguments_count; i++) { 94*84e872a0SLloyd Pique+ signature = get_next_argument_type(signature, &arg_type); 95*84e872a0SLloyd Pique+ if (i > 0) 96*84e872a0SLloyd Pique+ fprintf(f, ", "); 97*84e872a0SLloyd Pique+ 98*84e872a0SLloyd Pique+ switch (arg_type) { 99*84e872a0SLloyd Pique+ case 'u': 100*84e872a0SLloyd Pique+ fprintf(f, "%u", args[i].u); 101*84e872a0SLloyd Pique+ break; 102*84e872a0SLloyd Pique+ case 'i': 103*84e872a0SLloyd Pique+ fprintf(f, "%d", args[i].i); 104*84e872a0SLloyd Pique+ break; 105*84e872a0SLloyd Pique+ case 'f': 106*84e872a0SLloyd Pique+ fprintf(f, "%f", wl_fixed_to_double(args[i].f)); 107*84e872a0SLloyd Pique+ break; 108*84e872a0SLloyd Pique+ case 's': 109*84e872a0SLloyd Pique+ if (args[i].s) 110*84e872a0SLloyd Pique+ fprintf(f, "\"%s\"", args[i].s); 111*84e872a0SLloyd Pique+ else 112*84e872a0SLloyd Pique+ fprintf(f, "nil"); 113*84e872a0SLloyd Pique+ break; 114*84e872a0SLloyd Pique+ case 'o': 115*84e872a0SLloyd Pique+ if (args[i].o) { 116*84e872a0SLloyd Pique+ // Note: server logger should instead cast to 117*84e872a0SLloyd Pique+ // wl_resource, and use wl_resource_get_class 118*84e872a0SLloyd Pique+ // and wl_resource_get_id. 119*84e872a0SLloyd Pique+ arg_proxy = (struct wl_proxy *)(args[i].o); 120*84e872a0SLloyd Pique+ arg_class = wl_proxy_get_class(arg_proxy); 121*84e872a0SLloyd Pique+ 122*84e872a0SLloyd Pique+ fprintf(f, "%s@%u", 123*84e872a0SLloyd Pique+ arg_class ? arg_class : "[unknown]", 124*84e872a0SLloyd Pique+ wl_proxy_get_id(arg_proxy)); 125*84e872a0SLloyd Pique+ } else { 126*84e872a0SLloyd Pique+ fprintf(f, "nil"); 127*84e872a0SLloyd Pique+ } 128*84e872a0SLloyd Pique+ break; 129*84e872a0SLloyd Pique+ case 'n': 130*84e872a0SLloyd Pique+ fprintf(f, "new id %s@", 131*84e872a0SLloyd Pique+ (message->message->types[i]) 132*84e872a0SLloyd Pique+ ? message->message->types[i]->name 133*84e872a0SLloyd Pique+ : "[unknown]"); 134*84e872a0SLloyd Pique+ if (args[i].n != 0) 135*84e872a0SLloyd Pique+ fprintf(f, "%u", args[i].n); 136*84e872a0SLloyd Pique+ else 137*84e872a0SLloyd Pique+ fprintf(f, "nil"); 138*84e872a0SLloyd Pique+ break; 139*84e872a0SLloyd Pique+ case 'a': 140*84e872a0SLloyd Pique+ fprintf(f, "array"); 141*84e872a0SLloyd Pique+ break; 142*84e872a0SLloyd Pique+ case 'h': 143*84e872a0SLloyd Pique+ fprintf(f, "fd %d", args[i].h); 144*84e872a0SLloyd Pique+ break; 145*84e872a0SLloyd Pique+ } 146*84e872a0SLloyd Pique+ } 147*84e872a0SLloyd Pique+ 148*84e872a0SLloyd Pique+ fprintf(f, ")\n"); 149*84e872a0SLloyd Pique+ 150*84e872a0SLloyd Pique+ if (fclose(f) == 0) { 151*84e872a0SLloyd Pique+ fprintf(stderr, "%s", buffer); 152*84e872a0SLloyd Pique+ free(buffer); 153*84e872a0SLloyd Pique+ } 154*84e872a0SLloyd Pique+} 155*84e872a0SLloyd Pique+ 156*84e872a0SLloyd Pique static void 157*84e872a0SLloyd Pique callback_done(void *data, struct wl_callback *cb, uint32_t time) 158*84e872a0SLloyd Pique { 159*84e872a0SLloyd Pique@@ -218,12 +343,15 @@ logger_setup(struct compositor *compositor, struct client *client) 160*84e872a0SLloyd Pique client->display = wl_display_connect(socket); 161*84e872a0SLloyd Pique client->sequence_observer = wl_display_create_client_observer( 162*84e872a0SLloyd Pique client->display, client_sequence_observer_func, client); 163*84e872a0SLloyd Pique+ client->stderr_logger = wl_display_create_client_observer( 164*84e872a0SLloyd Pique+ client->display, client_log_to_stderr_demo, client); 165*84e872a0SLloyd Pique } 166*84e872a0SLloyd Pique 167*84e872a0SLloyd Pique static void 168*84e872a0SLloyd Pique logger_teardown(struct compositor *compositor, struct client *client) 169*84e872a0SLloyd Pique { 170*84e872a0SLloyd Pique wl_client_observer_destroy(client->sequence_observer); 171*84e872a0SLloyd Pique+ wl_client_observer_destroy(client->stderr_logger); 172*84e872a0SLloyd Pique wl_display_disconnect(client->display); 173*84e872a0SLloyd Pique 174*84e872a0SLloyd Pique wl_client_destroy(compositor->client); 175