From patchwork Wed May 30 18:40:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Colin Ian King X-Patchwork-Id: 162055 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id C83F0B7074 for ; Thu, 31 May 2012 04:40:51 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SZnpC-0002xP-G3 for incoming@patchwork.ozlabs.org; Wed, 30 May 2012 18:40:50 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SZnp5-0002vM-UP for fwts-devel@lists.ubuntu.com; Wed, 30 May 2012 18:40:44 +0000 Received: from cpc19-craw6-2-0-cust5.croy.cable.virginmedia.com ([77.102.228.6] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1SZnp5-0000sC-Bf for fwts-devel@lists.ubuntu.com; Wed, 30 May 2012 18:40:43 +0000 From: Colin King To: fwts-devel@lists.ubuntu.com Subject: [PATCH 4/4] lib: add HTML logging backend Date: Wed, 30 May 2012 19:40:38 +0100 Message-Id: <1338403238-14029-5-git-send-email-colin.king@canonical.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1338403238-14029-1-git-send-email-colin.king@canonical.com> References: <1338403238-14029-1-git-send-email-colin.king@canonical.com> X-BeenThere: fwts-devel@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Firmware Test Suite Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: fwts-devel-bounces@lists.ubuntu.com Errors-To: fwts-devel-bounces@lists.ubuntu.com From: Colin Ian King Signed-off-by: Colin Ian King Acked-by: Ivan Hu Acked-by: Keng-Yu Lin Tested-by: Chris Van Hoof --- src/lib/include/fwts_log.h | 8 +- src/lib/src/Makefile.am | 1 + src/lib/src/fwts_framework.c | 12 +- src/lib/src/fwts_log.c | 3 + src/lib/src/fwts_log_html.c | 297 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 313 insertions(+), 8 deletions(-) create mode 100644 src/lib/src/fwts_log_html.c diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h index 4e0f33a..a659baa 100644 --- a/src/lib/include/fwts_log.h +++ b/src/lib/include/fwts_log.h @@ -63,6 +63,7 @@ typedef enum { LOG_TYPE_PLAINTEXT = 0x00000001, LOG_TYPE_JSON = 0x00000002, LOG_TYPE_XML = 0x00000003, + LOG_TYPE_HTML = 0x00000004, } fwts_log_type; typedef struct log_t { @@ -84,9 +85,10 @@ typedef struct fwts_log_ops_t { void (*close)(fwts_log *); } fwts_log_ops; -fwts_log_ops fwts_log_plaintext_ops; -fwts_log_ops fwts_log_json_ops; -fwts_log_ops fwts_log_xml_ops; +extern fwts_log_ops fwts_log_plaintext_ops; +extern fwts_log_ops fwts_log_json_ops; +extern fwts_log_ops fwts_log_xml_ops; +extern fwts_log_ops fwts_log_html_ops; extern fwts_log_field fwts_log_filter; extern const char *fwts_log_format; diff --git a/src/lib/src/Makefile.am b/src/lib/src/Makefile.am index acea9cb..f846621 100644 --- a/src/lib/src/Makefile.am +++ b/src/lib/src/Makefile.am @@ -40,6 +40,7 @@ libfwts_la_SOURCES = \ fwts_log_plaintext.c \ fwts_log_json.c \ fwts_log_xml.c \ + fwts_log_html.c \ fwts_memorymap.c \ fwts_microcode.c \ fwts_mmap.c \ diff --git a/src/lib/src/fwts_framework.c b/src/lib/src/fwts_framework.c index 3f54fdb..721f4de 100644 --- a/src/lib/src/fwts_framework.c +++ b/src/lib/src/fwts_framework.c @@ -76,7 +76,7 @@ static fwts_option fwts_framework_options[] = { { "json-data-path", "j:", 1, "Specify path to fwts json data files - default is /usr/share/fwts." }, { "lp-tags-log", "", 0, "Output LaunchPad bug tags in results log." }, { "disassemble-aml", "", 0, "Disassemble AML from DSDT and SSDT tables." }, - { "log-type", "", 1, "Specify log type (plaintext, json or xml)." }, + { "log-type", "", 1, "Specify log type (plaintext, json, html or xml)." }, { NULL, NULL, 0, NULL } }; @@ -672,7 +672,7 @@ void fwts_framework_log(fwts_framework *fw, case LOG_ADVICE: fwts_log_nl(fw); snprintf(prefix, sizeof(prefix), "%s: ", str); - fwts_log_printf(fw->results, LOG_ADVICE, level, str, label, prefix, "%s", buffer); + fwts_log_printf(fw->results, field, level, str, label, prefix, "%s", buffer); fwts_log_nl(fw); break; case LOG_FAILED: @@ -680,7 +680,7 @@ void fwts_framework_log(fwts_framework *fw, fwts_summary_add(fw, fw->current_major_test->name, level, buffer); snprintf(prefix, sizeof(prefix), "%s [%s] %s: Test %d, ", str, fwts_log_level_to_str(level), label, fw->current_minor_test_num); - fwts_log_printf(fw->results, LOG_RESULT, level, str, label, prefix, "%s", buffer); + fwts_log_printf(fw->results, field, level, str, label, prefix, "%s", buffer); break; case LOG_PASSED: case LOG_WARNING: @@ -688,7 +688,7 @@ void fwts_framework_log(fwts_framework *fw, case LOG_ABORTED: snprintf(prefix, sizeof(prefix), "%s: Test %d, ", str, fw->current_minor_test_num); - fwts_log_printf(fw->results, LOG_RESULT, level, str, label, prefix, "%s", buffer); + fwts_log_printf(fw->results, field, level, str, label, prefix, "%s", buffer); break; case LOG_INFOONLY: break; /* no-op */ @@ -949,8 +949,10 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar fw->log_type = LOG_TYPE_JSON; else if (!strcmp(optarg, "xml")) fw->log_type = LOG_TYPE_XML; + else if (!strcmp(optarg, "html")) + fw->log_type = LOG_TYPE_HTML; else { - fprintf(stderr, "--log-type can be either plaintext or json.\n"); + fprintf(stderr, "--log-type can be either plaintext, xml, html or json.\n"); return FWTS_ERROR; } break; diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c index c764d55..fea7c41 100644 --- a/src/lib/src/fwts_log.c +++ b/src/lib/src/fwts_log.c @@ -432,6 +432,9 @@ fwts_log *fwts_log_open(const char *owner, const char *name, const char *mode, f case LOG_TYPE_XML: newlog->ops = &fwts_log_xml_ops; break; + case LOG_TYPE_HTML: + newlog->ops = &fwts_log_html_ops; + break; case LOG_TYPE_NONE: default: newlog->ops = &fwts_log_plaintext_ops; diff --git a/src/lib/src/fwts_log_html.c b/src/lib/src/fwts_log_html.c new file mode 100644 index 0000000..25f81ef --- /dev/null +++ b/src/lib/src/fwts_log_html.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2010-2012 Canonical + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "fwts.h" + +#define MAX_HTML_STACK (64) +#define HTML_INDENT (2) + +typedef struct { + const char *name; +} fwts_log_html_stack_t; + +static fwts_log_html_stack_t html_stack[MAX_HTML_STACK]; +static int html_stack_index = 0; + +static void fwts_log_html(fwts_log *log, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + fprintf(log->fp, "%*s", html_stack_index * HTML_INDENT, ""); + vfprintf(log->fp, fmt, args); + + va_end(args); +} + + +/* + * fwts_log_vprintf_html() + * vprintf to a log + */ +static int fwts_log_vprintf_html(fwts_log *log, + const fwts_log_field field, + const fwts_log_level level, + const char *status, + const char *label, + const char *prefix, + const char *fmt, + va_list args) +{ + struct tm tm; + time_t now; + char *str; + char *style; + char *code_start; + char *code_end; + + if (!((field & LOG_FIELD_MASK) & fwts_log_filter)) + return 0; + + if (field & (LOG_NEWLINE | LOG_SEPARATOR | LOG_DEBUG)) + return 0; + + time(&now); + localtime_r(&now, &tm); + + fwts_log_html(log, "\n"); + + if ((field & LOG_FIELD_MASK) != LOG_HEADING) { + fwts_log_html(log, " %2.2d/%2.2d/%-2.2d\n", + tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100); + fwts_log_html(log, " %2.2d:%2.2d:%2.2d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec); + } + + if (field & LOG_VERBATUM) { + code_start = "
";
+		code_end   = "
"; + } else { + code_start = ""; + code_end = ""; + } + + switch (field & LOG_FIELD_MASK) { + case LOG_ERROR: + fwts_log_html(log, " Error"); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "\n"); + break; + case LOG_WARNING: + fwts_log_html(log, " Warning%s", code_start); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "%s\n", code_end); + break; + case LOG_HEADING: + fwts_log_html(log, "%s", code_start); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "%s\n", code_end); + break; + case LOG_INFO: + fwts_log_html(log, " %s", code_start); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "%s\n", code_end); + break; + case LOG_PASSED: + fwts_log_html(log, "PASSED"); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "\n"); + break; + case LOG_FAILED: + switch (level) { + case LOG_LEVEL_CRITICAL: + style = " class=style_critical"; + break; + case LOG_LEVEL_HIGH: + style = " class=style_high"; + break; + case LOG_LEVEL_MEDIUM: + style = " class=style_medium"; + break; + case LOG_LEVEL_LOW: + style = " class=style_low"; + break; + case LOG_LEVEL_INFO: + case LOG_LEVEL_NONE: + default: + style = ""; + break; + } + str = fwts_log_level_to_str(level); + + fwts_log_html(log, " %s [%s]\n", style, *status ? status : "", str); + + fwts_log_html(log, " "); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "\n"); + break; + + case LOG_SKIPPED: + fwts_log_html(log, "Skipped%s", code_start); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "%s\n", code_end); + break; + + case LOG_SUMMARY: + fwts_log_html(log, " %s", code_start); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "%s\n", code_end); + break; + + case LOG_ADVICE: + fwts_log_html(log, " Advice%s", code_start); + vfprintf(log->fp, fmt, args); + fprintf(log->fp, "%s\n", code_end); + break; + + default: + break; + } + + fwts_log_html(log, "\n"); + fflush(log->fp); + + log->line_number++; + + return 0; +} + +/* + * fwts_log_underline_html() + * write an underline across log, using character ch as the underline + */ +static void fwts_log_underline_html(fwts_log *log, const int ch) +{ + /* No-op for html */ +} + +/* + * fwts_log_newline() + * write newline to log + */ +static void fwts_log_newline_html(fwts_log *log) +{ + /* No-op for html */ +} + +static void fwts_log_section_begin_html(fwts_log *log, const char *name) +{ + html_stack[html_stack_index].name = name; + + if (!strcmp(name, "summary")) { + fwts_log_html(log, "Summary\n"); + } else if (!strcmp(name, "heading")) { + fwts_log_html(log, "Firmware Test Suite\n"); + } else if (!strcmp(name, "subtest_info")) { + fwts_log_html(log, "\n"); + } else if (!strcmp(name, "failure")) { + fwts_log_html(log, "\n"); + } + + fflush(log->fp); + + if (html_stack_index < MAX_HTML_STACK) + html_stack_index++; + else { + fprintf(stderr, "html log stack overflow pushing section %s.\n", name); + exit(EXIT_FAILURE); + } +} + +static void fwts_log_section_end_html(fwts_log *log) +{ + if (html_stack_index > 0) { + html_stack_index--; + fflush(log->fp); + } else { + fprintf(stderr, "html log stack underflow.\n"); + exit(EXIT_FAILURE); + } + +} + +static void fwts_log_open_html(fwts_log *log) +{ + fwts_log_html(log, "\n"); + fwts_log_html(log, "\n"); + fwts_log_html(log, " fwts log\n"); + fwts_log_html(log, "\n"); + fwts_log_html(log, "\n"); + fwts_log_html(log, "\n"); + fflush(log->fp); + + fwts_log_html(log, "\n"); + fwts_log_html(log, "\n"); + + fwts_log_section_begin_html(log, "fwts"); +} + +static void fwts_log_close_html(fwts_log *log) +{ + fwts_log_section_end_html(log); + + fwts_log_html(log, "
\n"); + fwts_log_html(log, "\n"); + fwts_log_html(log, "\n"); + fflush(log->fp); +} + +fwts_log_ops fwts_log_html_ops = { + .vprintf = fwts_log_vprintf_html, + .underline = fwts_log_underline_html, + .newline = fwts_log_newline_html, + .section_begin = fwts_log_section_begin_html, + .section_end = fwts_log_section_end_html, + .open = fwts_log_open_html, + .close = fwts_log_close_html +};