Re: [PATCH BlueZ 1/3] shared/tester: Add option to print to monitor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
On Fri, Oct 5, 2018 at 12:00 PM Luiz Augusto von Dentz
<luiz.dentz@xxxxxxxxx> wrote:
>
> From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>
>
> This adds option -m/--monitor that can be used toguether with
> tester_monitor to send protocol data to be decoded by btmon.
>
> In addition to that this also logs the tester output into btmon since
> that has support to store its output on file this can be quite
> convenient for reporting.
> ---
>  src/shared/tester.c | 237 ++++++++++++++++++++++++++++++++++++++++----
>  src/shared/tester.h |   4 +
>  2 files changed, 220 insertions(+), 21 deletions(-)
>
> diff --git a/src/shared/tester.c b/src/shared/tester.c
> index 80d65110b..05c81a66d 100644
> --- a/src/shared/tester.c
> +++ b/src/shared/tester.c
> @@ -27,14 +27,19 @@
>
>  #include <stdio.h>
>  #include <errno.h>
> +#include <syslog.h>
>  #include <unistd.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <signal.h>
>  #include <sys/signalfd.h>
> +#include <sys/socket.h>
>
>  #include <glib.h>
>
> +#include "lib/bluetooth.h"
> +#include "lib/hci.h"
> +
>  #ifdef HAVE_VALGRIND_MEMCHECK_H
>  #include <valgrind/memcheck.h>
>  #endif
> @@ -54,15 +59,15 @@
>  #define COLOR_HIGHLIGHT        "\x1B[1;39m"
>
>  #define print_text(color, fmt, args...) \
> -               printf(color fmt COLOR_OFF "\n", ## args)
> +               tester_log(color fmt COLOR_OFF, ## args)
>
>  #define print_summary(label, color, value, fmt, args...) \
> -                       printf("%-52s " color "%-10s" COLOR_OFF fmt "\n", \
> +               tester_log("%-52s " color "%-10s" COLOR_OFF fmt, \
>                                                         label, value, ## args)
>
>  #define print_progress(name, color, fmt, args...) \
> -               printf(COLOR_HIGHLIGHT "%s" COLOR_OFF " - " \
> -                               color fmt COLOR_OFF "\n", name, ## args)
> +               tester_log(COLOR_HIGHLIGHT "%s" COLOR_OFF " - " \
> +                               color fmt COLOR_OFF, name, ## args)
>
>  enum test_result {
>         TEST_RESULT_NOT_RUN,
> @@ -100,6 +105,7 @@ struct test_case {
>  };
>
>  static GMainLoop *main_loop;
> +static char *tester_name;
>
>  static GList *test_list;
>  static GList *test_current;
> @@ -108,9 +114,25 @@ static GTimer *test_timer;
>  static gboolean option_version = FALSE;
>  static gboolean option_quiet = FALSE;
>  static gboolean option_debug = FALSE;
> +static gboolean option_monitor = FALSE;
>  static gboolean option_list = FALSE;
>  static const char *option_prefix = NULL;
>
> +struct monitor_hdr {
> +       uint16_t opcode;
> +       uint16_t index;
> +       uint16_t len;
> +       uint8_t  priority;
> +       uint8_t  ident_len;
> +} __attribute__((packed));
> +
> +struct monitor_l2cap_hdr {
> +       uint16_t cid;
> +       uint16_t psm;
> +} __attribute__((packed));
> +
> +static int monitor_fd = -1;
> +
>  static void test_destroy(gpointer data)
>  {
>         struct test_case *test = data;
> @@ -128,43 +150,208 @@ static void test_destroy(gpointer data)
>         free(test);
>  }
>
> -void tester_print(const char *format, ...)
> +static int monitor_open(void)
>  {
> -       va_list ap;
> +       struct sockaddr_hci addr;
> +       int fd;
> +
> +       if (!option_monitor)
> +               return -1;
> +
> +       if (monitor_fd >= 0)
> +               return monitor_fd;
> +
> +       fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
> +       if (fd < 0)
> +               return fd;
> +
> +       memset(&addr, 0, sizeof(addr));
> +       addr.hci_family = AF_BLUETOOTH;
> +       addr.hci_dev = HCI_DEV_NONE;
> +       addr.hci_channel = HCI_CHANNEL_LOGGING;
> +
> +       if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> +               option_monitor = FALSE;
> +               tester_debug("Failed to open monitor socket: %s",
> +                            strerror(errno));
> +               close(fd);
> +               return -1;
> +       }
> +
> +       monitor_fd = fd;
> +
> +       return fd;
> +}
> +
> +static void monitor_sendmsg(const char *label, int level, struct iovec *io,
> +                                                       size_t io_len)
> +{
> +       struct monitor_hdr hdr;
> +       struct msghdr msg;
> +       struct iovec iov[5];
> +       size_t i;
> +
> +       monitor_fd = monitor_open();
> +       if (monitor_fd < 0 || io_len > 3)
> +               return;
> +
> +       hdr.opcode = cpu_to_le16(0x0000);
> +       hdr.index = cpu_to_le16(0xffff);
> +       hdr.ident_len = strlen(label) + 1;
> +       hdr.len = cpu_to_le16(2 + hdr.ident_len);
> +       hdr.priority = level;
> +
> +       iov[0].iov_base = &hdr;
> +       iov[0].iov_len = sizeof(hdr);
> +
> +       iov[1].iov_base = (void *) label;
> +       iov[1].iov_len = hdr.ident_len;
> +
> +       memset(&msg, 0, sizeof(msg));
> +       msg.msg_iov = iov;
> +       msg.msg_iovlen = 2;
> +
> +       for (i = 0; i < io_len; i++) {
> +               iov[i + 2] = io[i];
> +               hdr.len += io[i].iov_len;
> +               msg.msg_iovlen++;
> +       }
>
> +       if (sendmsg(monitor_fd, &msg, 0) < 0) {
> +               /* Disable monitor */
> +               option_monitor = FALSE;
> +               tester_debug("Failed to send to monitor: %s", strerror(errno));
> +               close(monitor_fd);
> +               monitor_fd = -1;
> +       }
> +}
> +
> +static void monitor_vprintf(const char *id, int level, const char *format,
> +                                                               va_list ap)
> +{
> +       struct iovec iov;
> +       char *str;
> +
> +       if (!option_monitor)
> +               return;
> +
> +       if (vasprintf(&str, format, ap) < 0)
> +               return;
> +
> +       iov.iov_base = str;
> +       iov.iov_len = strlen(str) + 1;
> +
> +       monitor_sendmsg(id, level, &iov, 1);
> +
> +       free(str);
> +}
> +
> +static void tester_vprintf(const char *format, va_list ap)
> +{
>         if (tester_use_quiet())
>                 return;
>
>         printf("  %s", COLOR_WHITE);
> +       vprintf(format, ap);
> +       printf("%s\n", COLOR_OFF);
> +}
> +
> +static void tester_log(const char *format, ...)
> +{
> +       va_list ap;
> +
>         va_start(ap, format);
>         vprintf(format, ap);
> +       printf("\n");
> +       va_end(ap);
> +
> +       va_start(ap, format);
> +       monitor_vprintf(tester_name, LOG_INFO, format, ap);
> +       va_end(ap);
> +}
> +
> +void tester_print(const char *format, ...)
> +{
> +       va_list ap;
> +
> +       va_start(ap, format);
> +       tester_vprintf(format, ap);
> +       va_end(ap);
> +
> +       va_start(ap, format);
> +       monitor_vprintf(tester_name, LOG_INFO, format, ap);
>         va_end(ap);
> -       printf("%s\n", COLOR_OFF);
>  }
>
>  void tester_debug(const char *format, ...)
>  {
>         va_list ap;
>
> -       if (!tester_use_debug())
> -               return;
> +       va_start(ap, format);
> +       tester_vprintf(format, ap);
> +       va_end(ap);
>
> -       printf("  %s", COLOR_WHITE);
>         va_start(ap, format);
> -       vprintf(format, ap);
> +       monitor_vprintf(tester_name, LOG_DEBUG, format, ap);
>         va_end(ap);
> -       printf("%s\n", COLOR_OFF);
>  }
>
>  void tester_warn(const char *format, ...)
>  {
>         va_list ap;
>
> -       printf("  %s", COLOR_WHITE);
>         va_start(ap, format);
> -       vprintf(format, ap);
> +       tester_vprintf(format, ap);
> +       va_end(ap);
> +
> +       va_start(ap, format);
> +       monitor_vprintf(tester_name, LOG_WARNING, format, ap);
>         va_end(ap);
> -       printf("%s\n", COLOR_OFF);
> +}
> +
> +static void monitor_debug(const char *str, void *user_data)
> +{
> +       const char *label = user_data;
> +
> +       tester_debug("%s: %s", label, str);
> +}
> +
> +static void monitor_log(char dir, uint16_t cid, uint16_t psm, const void *data,
> +                                                               size_t len)
> +{
> +       struct iovec iov[3];
> +       struct monitor_l2cap_hdr hdr;
> +       uint8_t term = 0x00;
> +       char label[16];
> +
> +       if (snprintf(label, sizeof(label), "%c %s", dir, tester_name) < 0)
> +               return;
> +
> +       hdr.cid = cpu_to_le16(cid);
> +       hdr.psm = cpu_to_le16(psm);
> +
> +       iov[0].iov_base = &hdr;
> +       iov[0].iov_len = sizeof(hdr);
> +
> +       iov[1].iov_base = (void *) data;
> +       iov[1].iov_len = len;
> +
> +       /* Kernel won't forward if data is no NULL terminated */
> +       iov[2].iov_base = &term;
> +       iov[2].iov_len = sizeof(term);
> +
> +       monitor_sendmsg(label, LOG_INFO, iov, 3);
> +}
> +
> +void tester_monitor(char dir, uint16_t cid, uint16_t psm, const void *data,
> +                                                               size_t len)
> +{
> +       monitor_log(dir, cid, psm, data, len);
> +
> +       if (!tester_use_debug())
> +               return;
> +
> +       util_hexdump(dir, data, len, monitor_debug, (void *) tester_name);
>  }
>
>  static void default_pre_setup(const void *test_data)
> @@ -208,7 +395,7 @@ void tester_add_full(const char *name, const void *test_data,
>         }
>
>         if (option_list) {
> -               printf("%s\n", name);
> +               tester_log("%s", name);
>                 if (destroy)
>                         destroy(user_data);
>                 return;
> @@ -278,7 +465,7 @@ static int tester_summarize(void)
>         gdouble execution_time;
>         GList *list;
>
> -       printf("\n");
> +       tester_log("");
>         print_text(COLOR_HIGHLIGHT, "");
>         print_text(COLOR_HIGHLIGHT, "Test Summary");
>         print_text(COLOR_HIGHLIGHT, "------------");
> @@ -312,17 +499,17 @@ static int tester_summarize(void)
>                 }
>          }
>
> -       printf("\nTotal: %d, "
> +       tester_log("Total: %d, "
>                 COLOR_GREEN "Passed: %d (%.1f%%)" COLOR_OFF ", "
>                 COLOR_RED "Failed: %d" COLOR_OFF ", "
> -               COLOR_YELLOW "Not Run: %d" COLOR_OFF "\n",
> +               COLOR_YELLOW "Not Run: %d" COLOR_OFF,
>                         not_run + passed + failed, passed,
>                         (not_run + passed + failed) ?
>                         (float) passed * 100 / (not_run + passed + failed) : 0,
>                         failed, not_run);
>
>         execution_time = g_timer_elapsed(test_timer, NULL);
> -       printf("Overall execution time: %.3g seconds\n", execution_time);
> +       tester_log("Overall execution time: %.3g seconds", execution_time);
>
>         return failed;
>  }
> @@ -379,7 +566,7 @@ static void next_test_case(void)
>
>         test = test_current->data;
>
> -       printf("\n");
> +       tester_log("");
>         print_progress(test->name, COLOR_BLACK, "init");
>
>         test->start_time = g_timer_elapsed(test_timer, NULL);
> @@ -774,6 +961,8 @@ static GOptionEntry options[] = {
>                                 "Run tests without logging" },
>         { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug,
>                                 "Run tests with debug output" },
> +       { "monitor", 'm', 0, G_OPTION_ARG_NONE, &option_monitor,
> +                               "Enable monitor output" },
>         { "list", 'l', 0, G_OPTION_ARG_NONE, &option_list,
>                                 "Only list the tests to be run" },
>         { "prefix", 'p', 0, G_OPTION_ARG_STRING, &option_prefix,
> @@ -807,6 +996,12 @@ void tester_init(int *argc, char ***argv)
>
>         main_loop = g_main_loop_new(NULL, FALSE);
>
> +       tester_name = strrchr(*argv[0], '/');
> +       if (!tester_name)
> +               tester_name = strdup(*argv[0]);
> +       else
> +               tester_name = strdup(++tester_name);
> +
>         test_list = NULL;
>         test_current = NULL;
>  }
> diff --git a/src/shared/tester.h b/src/shared/tester.h
> index 83ef5de7a..96e8dc901 100644
> --- a/src/shared/tester.h
> +++ b/src/shared/tester.h
> @@ -22,6 +22,8 @@
>   */
>
>  #include <stdbool.h>
> +#include <stddef.h>
> +#include <stdint.h>
>
>  void tester_init(int *argc, char ***argv);
>  int tester_run(void);
> @@ -35,6 +37,8 @@ void tester_warn(const char *format, ...)
>                                 __attribute__((format(printf, 1, 2)));
>  void tester_debug(const char *format, ...)
>                                 __attribute__((format(printf, 1, 2)));
> +void tester_monitor(char dir, uint16_t cid, uint16_t psm, const void *data,
> +                                                               size_t len);
>
>  typedef void (*tester_destroy_func_t)(void *user_data);
>  typedef void (*tester_data_func_t)(const void *test_data);
> --
> 2.17.1

Applied.

-- 
Luiz Augusto von Dentz



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux