Message ID | 1338217284-8752-1-git-send-email-colin.king@canonical.com |
---|---|
State | Accepted |
Headers | show |
On Mon, May 28, 2012 at 11:01 PM, Colin King <colin.king@canonical.com> wrote: > From: Colin Ian King <colin.king@canonical.com> > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > doc/fwts.1 | 2 +- > src/lib/include/fwts_log.h | 1 + > src/lib/src/Makefile.am | 1 + > src/lib/src/fwts_framework.c | 4 +- > src/lib/src/fwts_log.c | 3 + > src/lib/src/fwts_log_xml.c | 186 ++++++++++++++++++++++++++++++++++++++++++ > 6 files changed, 195 insertions(+), 2 deletions(-) > create mode 100644 src/lib/src/fwts_log_xml.c > > diff --git a/doc/fwts.1 b/doc/fwts.1 > index 0d773cd..09eee56 100644 > --- a/doc/fwts.1 > +++ b/doc/fwts.1 > @@ -150,7 +150,7 @@ specify the information in each log line. The following specifiers are available > e.g. \-\-log\-format="%date %time [%field] (%owner): " > .TP > .B \-\-log\-type > -specify the log type. Currently plaintext and json log types are available and the > +specify the log type. Currently plaintext, json and xml log types are available and the > default is plaintext. > .TP > .B \-\-lp\-tags > diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h > index 8903bab..8027d41 100644 > --- a/src/lib/include/fwts_log.h > +++ b/src/lib/include/fwts_log.h > @@ -81,6 +81,7 @@ typedef struct fwts_log_ops_t { > > fwts_log_ops fwts_log_plaintext_ops; > fwts_log_ops fwts_log_json_ops; > +fwts_log_ops fwts_log_xml_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 cae1f91..acea9cb 100644 > --- a/src/lib/src/Makefile.am > +++ b/src/lib/src/Makefile.am > @@ -39,6 +39,7 @@ libfwts_la_SOURCES = \ > fwts_log.c \ > fwts_log_plaintext.c \ > fwts_log_json.c \ > + fwts_log_xml.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 1fcd88e..2b42982 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 or json)." }, > + { "log-type", "", 1, "Specify log type (plaintext, json or xml)." }, > { NULL, NULL, 0, NULL } > }; > > @@ -1040,6 +1040,8 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar > fw->log_type = LOG_TYPE_PLAINTEXT; > else if (!strcmp(optarg, "json")) > fw->log_type = LOG_TYPE_JSON; > + else if (!strcmp(optarg, "xml")) > + fw->log_type = LOG_TYPE_XML; > else { > fprintf(stderr, "--log-type can be either plaintext or json.\n"); > return FWTS_ERROR; > diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c > index 5331fff..2b11441 100644 > --- a/src/lib/src/fwts_log.c > +++ b/src/lib/src/fwts_log.c > @@ -390,6 +390,9 @@ fwts_log *fwts_log_open(const char *owner, const char *name, const char *mode, f > case LOG_TYPE_PLAINTEXT: > newlog->ops = &fwts_log_plaintext_ops; > break; > + case LOG_TYPE_XML: > + newlog->ops = &fwts_log_xml_ops; > + break; > case LOG_TYPE_NONE: > default: > newlog->ops = &fwts_log_plaintext_ops; > diff --git a/src/lib/src/fwts_log_xml.c b/src/lib/src/fwts_log_xml.c > new file mode 100644 > index 0000000..57b530b > --- /dev/null > +++ b/src/lib/src/fwts_log_xml.c > @@ -0,0 +1,186 @@ > +/* > + * 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 <stdlib.h> > +#include <stdio.h> > +#include <stdarg.h> > +#include <string.h> > +#include <unistd.h> > +#include <sys/ioctl.h> > +#include <time.h> > + > +#include "fwts.h" > + > +#define MAX_XML_STACK (64) > +#define XML_INDENT (4) > + > +typedef struct { > + const char *name; > +} fwts_log_xml_stack_t; > + > +static fwts_log_xml_stack_t xml_stack[MAX_XML_STACK]; > +static int xml_stack_index = 0; > + > +/* > + * fwts_log_vprintf_xml() > + * vprintf to a log > + */ > +static int fwts_log_vprintf_xml(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) > +{ > + char buffer[4096]; > + struct tm tm; > + time_t now; > + char *str; > + > + 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); > + > + fprintf(log->fp, "%*s<logentry>\n", xml_stack_index * XML_INDENT, ""); > + > + fprintf(log->fp, "%*s<line_num>%d</line_num>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", log->line_number); > + > + fprintf(log->fp, "%*s<date>%2.2d/%2.2d/%-2.2d</date>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100); > + > + fprintf(log->fp, "%*s<time>%2.2d:%2.2d:%2.2d</time>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", tm.tm_hour, tm.tm_min, tm.tm_sec); > + > + fprintf(log->fp, "%*s<field_type>%s</field_type>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", fwts_log_field_to_str_full(field)); > + > + str = fwts_log_level_to_str(level); > + if (!strcmp(str, " ")) > + str = "None"; > + > + fprintf(log->fp, "%*s<level>%s</level>\n", > + (xml_stack_index + 1) * XML_INDENT, "", str); > + > + fprintf(log->fp, "%*s<status>%s</status>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", *status ? status : "None"); > + > + fprintf(log->fp, "%*s<failure_label>%s</failure_label>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", label && *label ? label : "None"); > + > + vsnprintf(buffer, sizeof(buffer), fmt, args); > + fprintf(log->fp, "%*s<log_text>%s</log_text>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", buffer); > + > + fprintf(log->fp, "%*s</logentry>\n", xml_stack_index * XML_INDENT, ""); > + fflush(log->fp); > + > + log->line_number++; > + > + return 0; > +} > + > +/* > + * fwts_log_underline_xml() > + * write an underline across log, using character ch as the underline > + */ > +static void fwts_log_underline_xml(fwts_log *log, const int ch) > +{ > + /* No-op for xml */ > +} > + > +/* > + * fwts_log_newline() > + * write newline to log > + */ > +static void fwts_log_newline_xml(fwts_log *log) > +{ > + /* No-op for xml */ > +} > + > +static void fwts_log_section_begin_xml(fwts_log *log, const char *name) > +{ > + xml_stack[xml_stack_index].name = name; > + > + fprintf(log->fp, "%*s<%s>\n", xml_stack_index * XML_INDENT, "", name); > + fflush(log->fp); > + > + if (xml_stack_index < MAX_XML_STACK) > + xml_stack_index++; > + else { > + fprintf(stderr, "xml log stack overflow pushing section %s.\n", name); > + exit(EXIT_FAILURE); > + } > +} > + > +static void fwts_log_section_end_xml(fwts_log *log) > +{ > + if (xml_stack_index > 0) { > + xml_stack_index--; > + fprintf(log->fp, "%*s</%s>\n", xml_stack_index * XML_INDENT, > + "", xml_stack[xml_stack_index].name); > + fflush(log->fp); > + } else { > + fprintf(stderr, "xml log stack underflow.\n"); > + exit(EXIT_FAILURE); > + } > + > +} > + > +static void fwts_log_open_xml(fwts_log *log) > +{ > + char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; > + > + fwrite(xml_header, 1, strlen(xml_header), log->fp); > + fflush(log->fp); > + > + fwts_log_section_begin_xml(log, "fwts"); > +} > + > +static void fwts_log_close_xml(fwts_log *log) > +{ > + fwts_log_section_end_xml(log); > + > + fwrite("\n", 1, 1, log->fp); > + fflush(log->fp); > +} > + > +fwts_log_ops fwts_log_xml_ops = { > + .vprintf = fwts_log_vprintf_xml, > + .underline = fwts_log_underline_xml, > + .newline = fwts_log_newline_xml, > + .section_begin = fwts_log_section_begin_xml, > + .section_end = fwts_log_section_end_xml, > + .open = fwts_log_open_xml, > + .close = fwts_log_close_xml > +}; > -- > 1.7.10 > Acked-by: Keng-Yu Lin <kengyu@canonical.com>
On 05/28/2012 11:01 PM, Colin King wrote: > From: Colin Ian King<colin.king@canonical.com> > > Signed-off-by: Colin Ian King<colin.king@canonical.com> > --- > doc/fwts.1 | 2 +- > src/lib/include/fwts_log.h | 1 + > src/lib/src/Makefile.am | 1 + > src/lib/src/fwts_framework.c | 4 +- > src/lib/src/fwts_log.c | 3 + > src/lib/src/fwts_log_xml.c | 186 ++++++++++++++++++++++++++++++++++++++++++ > 6 files changed, 195 insertions(+), 2 deletions(-) > create mode 100644 src/lib/src/fwts_log_xml.c > > diff --git a/doc/fwts.1 b/doc/fwts.1 > index 0d773cd..09eee56 100644 > --- a/doc/fwts.1 > +++ b/doc/fwts.1 > @@ -150,7 +150,7 @@ specify the information in each log line. The following specifiers are available > e.g. \-\-log\-format="%date %time [%field] (%owner): " > .TP > .B \-\-log\-type > -specify the log type. Currently plaintext and json log types are available and the > +specify the log type. Currently plaintext, json and xml log types are available and the > default is plaintext. > .TP > .B \-\-lp\-tags > diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h > index 8903bab..8027d41 100644 > --- a/src/lib/include/fwts_log.h > +++ b/src/lib/include/fwts_log.h > @@ -81,6 +81,7 @@ typedef struct fwts_log_ops_t { > > fwts_log_ops fwts_log_plaintext_ops; > fwts_log_ops fwts_log_json_ops; > +fwts_log_ops fwts_log_xml_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 cae1f91..acea9cb 100644 > --- a/src/lib/src/Makefile.am > +++ b/src/lib/src/Makefile.am > @@ -39,6 +39,7 @@ libfwts_la_SOURCES = \ > fwts_log.c \ > fwts_log_plaintext.c \ > fwts_log_json.c \ > + fwts_log_xml.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 1fcd88e..2b42982 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 or json)." }, > + { "log-type", "", 1, "Specify log type (plaintext, json or xml)." }, > { NULL, NULL, 0, NULL } > }; > > @@ -1040,6 +1040,8 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar > fw->log_type = LOG_TYPE_PLAINTEXT; > else if (!strcmp(optarg, "json")) > fw->log_type = LOG_TYPE_JSON; > + else if (!strcmp(optarg, "xml")) > + fw->log_type = LOG_TYPE_XML; > else { > fprintf(stderr, "--log-type can be either plaintext or json.\n"); > return FWTS_ERROR; > diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c > index 5331fff..2b11441 100644 > --- a/src/lib/src/fwts_log.c > +++ b/src/lib/src/fwts_log.c > @@ -390,6 +390,9 @@ fwts_log *fwts_log_open(const char *owner, const char *name, const char *mode, f > case LOG_TYPE_PLAINTEXT: > newlog->ops =&fwts_log_plaintext_ops; > break; > + case LOG_TYPE_XML: > + newlog->ops =&fwts_log_xml_ops; > + break; > case LOG_TYPE_NONE: > default: > newlog->ops =&fwts_log_plaintext_ops; > diff --git a/src/lib/src/fwts_log_xml.c b/src/lib/src/fwts_log_xml.c > new file mode 100644 > index 0000000..57b530b > --- /dev/null > +++ b/src/lib/src/fwts_log_xml.c > @@ -0,0 +1,186 @@ > +/* > + * 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<stdlib.h> > +#include<stdio.h> > +#include<stdarg.h> > +#include<string.h> > +#include<unistd.h> > +#include<sys/ioctl.h> > +#include<time.h> > + > +#include "fwts.h" > + > +#define MAX_XML_STACK (64) > +#define XML_INDENT (4) > + > +typedef struct { > + const char *name; > +} fwts_log_xml_stack_t; > + > +static fwts_log_xml_stack_t xml_stack[MAX_XML_STACK]; > +static int xml_stack_index = 0; > + > +/* > + * fwts_log_vprintf_xml() > + * vprintf to a log > + */ > +static int fwts_log_vprintf_xml(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) > +{ > + char buffer[4096]; > + struct tm tm; > + time_t now; > + char *str; > + > + 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); > + > + fprintf(log->fp, "%*s<logentry>\n", xml_stack_index * XML_INDENT, ""); > + > + fprintf(log->fp, "%*s<line_num>%d</line_num>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", log->line_number); > + > + fprintf(log->fp, "%*s<date>%2.2d/%2.2d/%-2.2d</date>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100); > + > + fprintf(log->fp, "%*s<time>%2.2d:%2.2d:%2.2d</time>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", tm.tm_hour, tm.tm_min, tm.tm_sec); > + > + fprintf(log->fp, "%*s<field_type>%s</field_type>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", fwts_log_field_to_str_full(field)); > + > + str = fwts_log_level_to_str(level); > + if (!strcmp(str, " ")) > + str = "None"; > + > + fprintf(log->fp, "%*s<level>%s</level>\n", > + (xml_stack_index + 1) * XML_INDENT, "", str); > + > + fprintf(log->fp, "%*s<status>%s</status>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", *status ? status : "None"); > + > + fprintf(log->fp, "%*s<failure_label>%s</failure_label>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", label&& *label ? label : "None"); > + > + vsnprintf(buffer, sizeof(buffer), fmt, args); > + fprintf(log->fp, "%*s<log_text>%s</log_text>\n", > + (xml_stack_index + 1) * XML_INDENT, > + "", buffer); > + > + fprintf(log->fp, "%*s</logentry>\n", xml_stack_index * XML_INDENT, ""); > + fflush(log->fp); > + > + log->line_number++; > + > + return 0; > +} > + > +/* > + * fwts_log_underline_xml() > + * write an underline across log, using character ch as the underline > + */ > +static void fwts_log_underline_xml(fwts_log *log, const int ch) > +{ > + /* No-op for xml */ > +} > + > +/* > + * fwts_log_newline() > + * write newline to log > + */ > +static void fwts_log_newline_xml(fwts_log *log) > +{ > + /* No-op for xml */ > +} > + > +static void fwts_log_section_begin_xml(fwts_log *log, const char *name) > +{ > + xml_stack[xml_stack_index].name = name; > + > + fprintf(log->fp, "%*s<%s>\n", xml_stack_index * XML_INDENT, "", name); > + fflush(log->fp); > + > + if (xml_stack_index< MAX_XML_STACK) > + xml_stack_index++; > + else { > + fprintf(stderr, "xml log stack overflow pushing section %s.\n", name); > + exit(EXIT_FAILURE); > + } > +} > + > +static void fwts_log_section_end_xml(fwts_log *log) > +{ > + if (xml_stack_index> 0) { > + xml_stack_index--; > + fprintf(log->fp, "%*s</%s>\n", xml_stack_index * XML_INDENT, > + "", xml_stack[xml_stack_index].name); > + fflush(log->fp); > + } else { > + fprintf(stderr, "xml log stack underflow.\n"); > + exit(EXIT_FAILURE); > + } > + > +} > + > +static void fwts_log_open_xml(fwts_log *log) > +{ > + char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; > + > + fwrite(xml_header, 1, strlen(xml_header), log->fp); > + fflush(log->fp); > + > + fwts_log_section_begin_xml(log, "fwts"); > +} > + > +static void fwts_log_close_xml(fwts_log *log) > +{ > + fwts_log_section_end_xml(log); > + > + fwrite("\n", 1, 1, log->fp); > + fflush(log->fp); > +} > + > +fwts_log_ops fwts_log_xml_ops = { > + .vprintf = fwts_log_vprintf_xml, > + .underline = fwts_log_underline_xml, > + .newline = fwts_log_newline_xml, > + .section_begin = fwts_log_section_begin_xml, > + .section_end = fwts_log_section_end_xml, > + .open = fwts_log_open_xml, > + .close = fwts_log_close_xml > +}; Hi Colin, I've checked the xml file(results.log). It seems that it doesn't close properly (missing </tests> and </fwts>). Except that, all looks good to me. Thanks! Best regards, Ivan Acked-by: Ivan Hu<ivan.hu@canonical.com>
On Fri, Jun 1, 2012 at 10:43 AM, IvanHu <ivan.hu@canonical.com> wrote: > On 05/28/2012 11:01 PM, Colin King wrote: >> >> From: Colin Ian King<colin.king@canonical.com> >> >> Signed-off-by: Colin Ian King<colin.king@canonical.com> >> --- >> doc/fwts.1 | 2 +- >> src/lib/include/fwts_log.h | 1 + >> src/lib/src/Makefile.am | 1 + >> src/lib/src/fwts_framework.c | 4 +- >> src/lib/src/fwts_log.c | 3 + >> src/lib/src/fwts_log_xml.c | 186 >> ++++++++++++++++++++++++++++++++++++++++++ >> 6 files changed, 195 insertions(+), 2 deletions(-) >> create mode 100644 src/lib/src/fwts_log_xml.c >> >> diff --git a/doc/fwts.1 b/doc/fwts.1 >> index 0d773cd..09eee56 100644 >> --- a/doc/fwts.1 >> +++ b/doc/fwts.1 >> @@ -150,7 +150,7 @@ specify the information in each log line. The >> following specifiers are available >> e.g. \-\-log\-format="%date %time [%field] (%owner): " >> .TP >> .B \-\-log\-type >> -specify the log type. Currently plaintext and json log types are >> available and the >> +specify the log type. Currently plaintext, json and xml log types are >> available and the >> default is plaintext. >> .TP >> .B \-\-lp\-tags >> diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h >> index 8903bab..8027d41 100644 >> --- a/src/lib/include/fwts_log.h >> +++ b/src/lib/include/fwts_log.h >> @@ -81,6 +81,7 @@ typedef struct fwts_log_ops_t { >> >> fwts_log_ops fwts_log_plaintext_ops; >> fwts_log_ops fwts_log_json_ops; >> +fwts_log_ops fwts_log_xml_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 cae1f91..acea9cb 100644 >> --- a/src/lib/src/Makefile.am >> +++ b/src/lib/src/Makefile.am >> @@ -39,6 +39,7 @@ libfwts_la_SOURCES = \ >> fwts_log.c \ >> fwts_log_plaintext.c \ >> fwts_log_json.c \ >> + fwts_log_xml.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 1fcd88e..2b42982 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 or >> json)." }, >> + { "log-type", "", 1, "Specify log type (plaintext, >> json or xml)." }, >> { NULL, NULL, 0, NULL } >> }; >> >> @@ -1040,6 +1040,8 @@ int fwts_framework_options_handler(fwts_framework >> *fw, int argc, char * const ar >> fw->log_type = LOG_TYPE_PLAINTEXT; >> else if (!strcmp(optarg, "json")) >> fw->log_type = LOG_TYPE_JSON; >> + else if (!strcmp(optarg, "xml")) >> + fw->log_type = LOG_TYPE_XML; >> else { >> fprintf(stderr, "--log-type can be either >> plaintext or json.\n"); >> return FWTS_ERROR; >> diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c >> index 5331fff..2b11441 100644 >> --- a/src/lib/src/fwts_log.c >> +++ b/src/lib/src/fwts_log.c >> @@ -390,6 +390,9 @@ fwts_log *fwts_log_open(const char *owner, const char >> *name, const char *mode, f >> case LOG_TYPE_PLAINTEXT: >> newlog->ops =&fwts_log_plaintext_ops; >> break; >> + case LOG_TYPE_XML: >> + newlog->ops =&fwts_log_xml_ops; >> + break; >> case LOG_TYPE_NONE: >> default: >> newlog->ops =&fwts_log_plaintext_ops; >> diff --git a/src/lib/src/fwts_log_xml.c b/src/lib/src/fwts_log_xml.c >> new file mode 100644 >> index 0000000..57b530b >> --- /dev/null >> +++ b/src/lib/src/fwts_log_xml.c >> @@ -0,0 +1,186 @@ >> +/* >> + * 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<stdlib.h> >> +#include<stdio.h> >> +#include<stdarg.h> >> +#include<string.h> >> +#include<unistd.h> >> +#include<sys/ioctl.h> >> +#include<time.h> >> + >> +#include "fwts.h" >> + >> +#define MAX_XML_STACK (64) >> +#define XML_INDENT (4) >> + >> +typedef struct { >> + const char *name; >> +} fwts_log_xml_stack_t; >> + >> +static fwts_log_xml_stack_t xml_stack[MAX_XML_STACK]; >> +static int xml_stack_index = 0; >> + >> +/* >> + * fwts_log_vprintf_xml() >> + * vprintf to a log >> + */ >> +static int fwts_log_vprintf_xml(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) >> +{ >> + char buffer[4096]; >> + struct tm tm; >> + time_t now; >> + char *str; >> + >> + 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); >> + >> + fprintf(log->fp, "%*s<logentry>\n", xml_stack_index * XML_INDENT, >> ""); >> + >> + fprintf(log->fp, "%*s<line_num>%d</line_num>\n", >> + (xml_stack_index + 1) * XML_INDENT, >> + "", log->line_number); >> + >> + fprintf(log->fp, "%*s<date>%2.2d/%2.2d/%-2.2d</date>\n", >> + (xml_stack_index + 1) * XML_INDENT, >> + "", tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100); >> + >> + fprintf(log->fp, "%*s<time>%2.2d:%2.2d:%2.2d</time>\n", >> + (xml_stack_index + 1) * XML_INDENT, >> + "", tm.tm_hour, tm.tm_min, tm.tm_sec); >> + >> + fprintf(log->fp, "%*s<field_type>%s</field_type>\n", >> + (xml_stack_index + 1) * XML_INDENT, >> + "", fwts_log_field_to_str_full(field)); >> + >> + str = fwts_log_level_to_str(level); >> + if (!strcmp(str, " ")) >> + str = "None"; >> + >> + fprintf(log->fp, "%*s<level>%s</level>\n", >> + (xml_stack_index + 1) * XML_INDENT, "", str); >> + >> + fprintf(log->fp, "%*s<status>%s</status>\n", >> + (xml_stack_index + 1) * XML_INDENT, >> + "", *status ? status : "None"); >> + >> + fprintf(log->fp, "%*s<failure_label>%s</failure_label>\n", >> + (xml_stack_index + 1) * XML_INDENT, >> + "", label&& *label ? label : "None"); >> >> + >> + vsnprintf(buffer, sizeof(buffer), fmt, args); >> + fprintf(log->fp, "%*s<log_text>%s</log_text>\n", >> + (xml_stack_index + 1) * XML_INDENT, >> + "", buffer); >> + >> + fprintf(log->fp, "%*s</logentry>\n", xml_stack_index * XML_INDENT, >> ""); >> + fflush(log->fp); >> + >> + log->line_number++; >> + >> + return 0; >> +} >> + >> +/* >> + * fwts_log_underline_xml() >> + * write an underline across log, using character ch as the underline >> + */ >> +static void fwts_log_underline_xml(fwts_log *log, const int ch) >> +{ >> + /* No-op for xml */ >> +} >> + >> +/* >> + * fwts_log_newline() >> + * write newline to log >> + */ >> +static void fwts_log_newline_xml(fwts_log *log) >> +{ >> + /* No-op for xml */ >> +} >> + >> +static void fwts_log_section_begin_xml(fwts_log *log, const char *name) >> +{ >> + xml_stack[xml_stack_index].name = name; >> + >> + fprintf(log->fp, "%*s<%s>\n", xml_stack_index * XML_INDENT, "", >> name); >> + fflush(log->fp); >> + >> + if (xml_stack_index< MAX_XML_STACK) >> + xml_stack_index++; >> + else { >> + fprintf(stderr, "xml log stack overflow pushing section >> %s.\n", name); >> + exit(EXIT_FAILURE); >> + } >> +} >> + >> +static void fwts_log_section_end_xml(fwts_log *log) >> +{ >> + if (xml_stack_index> 0) { >> + xml_stack_index--; >> + fprintf(log->fp, "%*s</%s>\n", xml_stack_index * >> XML_INDENT, >> + "", xml_stack[xml_stack_index].name); >> + fflush(log->fp); >> + } else { >> + fprintf(stderr, "xml log stack underflow.\n"); >> + exit(EXIT_FAILURE); >> + } >> + >> +} >> + >> +static void fwts_log_open_xml(fwts_log *log) >> +{ >> + char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\" >> ?>\n"; >> + >> + fwrite(xml_header, 1, strlen(xml_header), log->fp); >> + fflush(log->fp); >> + >> + fwts_log_section_begin_xml(log, "fwts"); >> +} >> + >> +static void fwts_log_close_xml(fwts_log *log) >> +{ >> + fwts_log_section_end_xml(log); >> + >> + fwrite("\n", 1, 1, log->fp); >> + fflush(log->fp); >> +} >> + >> +fwts_log_ops fwts_log_xml_ops = { >> + .vprintf = fwts_log_vprintf_xml, >> + .underline = fwts_log_underline_xml, >> + .newline = fwts_log_newline_xml, >> + .section_begin = fwts_log_section_begin_xml, >> + .section_end = fwts_log_section_end_xml, >> + .open = fwts_log_open_xml, >> + .close = fwts_log_close_xml >> +}; > > > Hi Colin, > > I've checked the xml file(results.log). It seems that it doesn't close > properly (missing </tests> and </fwts>). > Except that, all looks good to me. Thanks! > I formed another patch fixing this.
On 01/06/12 09:21, Keng-Yu Lin wrote: > On Fri, Jun 1, 2012 at 10:43 AM, IvanHu <ivan.hu@canonical.com> wrote: >> On 05/28/2012 11:01 PM, Colin King wrote: >>> >>> From: Colin Ian King<colin.king@canonical.com> >>> >>> Signed-off-by: Colin Ian King<colin.king@canonical.com> >>> --- >>> doc/fwts.1 | 2 +- >>> src/lib/include/fwts_log.h | 1 + >>> src/lib/src/Makefile.am | 1 + >>> src/lib/src/fwts_framework.c | 4 +- >>> src/lib/src/fwts_log.c | 3 + >>> src/lib/src/fwts_log_xml.c | 186 >>> ++++++++++++++++++++++++++++++++++++++++++ >>> 6 files changed, 195 insertions(+), 2 deletions(-) >>> create mode 100644 src/lib/src/fwts_log_xml.c >>> >>> diff --git a/doc/fwts.1 b/doc/fwts.1 >>> index 0d773cd..09eee56 100644 >>> --- a/doc/fwts.1 >>> +++ b/doc/fwts.1 >>> @@ -150,7 +150,7 @@ specify the information in each log line. The >>> following specifiers are available >>> e.g. \-\-log\-format="%date %time [%field] (%owner): " >>> .TP >>> .B \-\-log\-type >>> -specify the log type. Currently plaintext and json log types are >>> available and the >>> +specify the log type. Currently plaintext, json and xml log types are >>> available and the >>> default is plaintext. >>> .TP >>> .B \-\-lp\-tags >>> diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h >>> index 8903bab..8027d41 100644 >>> --- a/src/lib/include/fwts_log.h >>> +++ b/src/lib/include/fwts_log.h >>> @@ -81,6 +81,7 @@ typedef struct fwts_log_ops_t { >>> >>> fwts_log_ops fwts_log_plaintext_ops; >>> fwts_log_ops fwts_log_json_ops; >>> +fwts_log_ops fwts_log_xml_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 cae1f91..acea9cb 100644 >>> --- a/src/lib/src/Makefile.am >>> +++ b/src/lib/src/Makefile.am >>> @@ -39,6 +39,7 @@ libfwts_la_SOURCES = \ >>> fwts_log.c \ >>> fwts_log_plaintext.c \ >>> fwts_log_json.c \ >>> + fwts_log_xml.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 1fcd88e..2b42982 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 or >>> json)." }, >>> + { "log-type", "", 1, "Specify log type (plaintext, >>> json or xml)." }, >>> { NULL, NULL, 0, NULL } >>> }; >>> >>> @@ -1040,6 +1040,8 @@ int fwts_framework_options_handler(fwts_framework >>> *fw, int argc, char * const ar >>> fw->log_type = LOG_TYPE_PLAINTEXT; >>> else if (!strcmp(optarg, "json")) >>> fw->log_type = LOG_TYPE_JSON; >>> + else if (!strcmp(optarg, "xml")) >>> + fw->log_type = LOG_TYPE_XML; >>> else { >>> fprintf(stderr, "--log-type can be either >>> plaintext or json.\n"); >>> return FWTS_ERROR; >>> diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c >>> index 5331fff..2b11441 100644 >>> --- a/src/lib/src/fwts_log.c >>> +++ b/src/lib/src/fwts_log.c >>> @@ -390,6 +390,9 @@ fwts_log *fwts_log_open(const char *owner, const char >>> *name, const char *mode, f >>> case LOG_TYPE_PLAINTEXT: >>> newlog->ops =&fwts_log_plaintext_ops; >>> break; >>> + case LOG_TYPE_XML: >>> + newlog->ops =&fwts_log_xml_ops; >>> + break; >>> case LOG_TYPE_NONE: >>> default: >>> newlog->ops =&fwts_log_plaintext_ops; >>> diff --git a/src/lib/src/fwts_log_xml.c b/src/lib/src/fwts_log_xml.c >>> new file mode 100644 >>> index 0000000..57b530b >>> --- /dev/null >>> +++ b/src/lib/src/fwts_log_xml.c >>> @@ -0,0 +1,186 @@ >>> +/* >>> + * 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<stdlib.h> >>> +#include<stdio.h> >>> +#include<stdarg.h> >>> +#include<string.h> >>> +#include<unistd.h> >>> +#include<sys/ioctl.h> >>> +#include<time.h> >>> + >>> +#include "fwts.h" >>> + >>> +#define MAX_XML_STACK (64) >>> +#define XML_INDENT (4) >>> + >>> +typedef struct { >>> + const char *name; >>> +} fwts_log_xml_stack_t; >>> + >>> +static fwts_log_xml_stack_t xml_stack[MAX_XML_STACK]; >>> +static int xml_stack_index = 0; >>> + >>> +/* >>> + * fwts_log_vprintf_xml() >>> + * vprintf to a log >>> + */ >>> +static int fwts_log_vprintf_xml(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) >>> +{ >>> + char buffer[4096]; >>> + struct tm tm; >>> + time_t now; >>> + char *str; >>> + >>> + 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); >>> + >>> + fprintf(log->fp, "%*s<logentry>\n", xml_stack_index * XML_INDENT, >>> ""); >>> + >>> + fprintf(log->fp, "%*s<line_num>%d</line_num>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", log->line_number); >>> + >>> + fprintf(log->fp, "%*s<date>%2.2d/%2.2d/%-2.2d</date>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100); >>> + >>> + fprintf(log->fp, "%*s<time>%2.2d:%2.2d:%2.2d</time>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", tm.tm_hour, tm.tm_min, tm.tm_sec); >>> + >>> + fprintf(log->fp, "%*s<field_type>%s</field_type>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", fwts_log_field_to_str_full(field)); >>> + >>> + str = fwts_log_level_to_str(level); >>> + if (!strcmp(str, " ")) >>> + str = "None"; >>> + >>> + fprintf(log->fp, "%*s<level>%s</level>\n", >>> + (xml_stack_index + 1) * XML_INDENT, "", str); >>> + >>> + fprintf(log->fp, "%*s<status>%s</status>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", *status ? status : "None"); >>> + >>> + fprintf(log->fp, "%*s<failure_label>%s</failure_label>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", label&& *label ? label : "None"); >>> >>> + >>> + vsnprintf(buffer, sizeof(buffer), fmt, args); >>> + fprintf(log->fp, "%*s<log_text>%s</log_text>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", buffer); >>> + >>> + fprintf(log->fp, "%*s</logentry>\n", xml_stack_index * XML_INDENT, >>> ""); >>> + fflush(log->fp); >>> + >>> + log->line_number++; >>> + >>> + return 0; >>> +} >>> + >>> +/* >>> + * fwts_log_underline_xml() >>> + * write an underline across log, using character ch as the underline >>> + */ >>> +static void fwts_log_underline_xml(fwts_log *log, const int ch) >>> +{ >>> + /* No-op for xml */ >>> +} >>> + >>> +/* >>> + * fwts_log_newline() >>> + * write newline to log >>> + */ >>> +static void fwts_log_newline_xml(fwts_log *log) >>> +{ >>> + /* No-op for xml */ >>> +} >>> + >>> +static void fwts_log_section_begin_xml(fwts_log *log, const char *name) >>> +{ >>> + xml_stack[xml_stack_index].name = name; >>> + >>> + fprintf(log->fp, "%*s<%s>\n", xml_stack_index * XML_INDENT, "", >>> name); >>> + fflush(log->fp); >>> + >>> + if (xml_stack_index< MAX_XML_STACK) >>> + xml_stack_index++; >>> + else { >>> + fprintf(stderr, "xml log stack overflow pushing section >>> %s.\n", name); >>> + exit(EXIT_FAILURE); >>> + } >>> +} >>> + >>> +static void fwts_log_section_end_xml(fwts_log *log) >>> +{ >>> + if (xml_stack_index> 0) { >>> + xml_stack_index--; >>> + fprintf(log->fp, "%*s</%s>\n", xml_stack_index * >>> XML_INDENT, >>> + "", xml_stack[xml_stack_index].name); >>> + fflush(log->fp); >>> + } else { >>> + fprintf(stderr, "xml log stack underflow.\n"); >>> + exit(EXIT_FAILURE); >>> + } >>> + >>> +} >>> + >>> +static void fwts_log_open_xml(fwts_log *log) >>> +{ >>> + char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\" >>> ?>\n"; >>> + >>> + fwrite(xml_header, 1, strlen(xml_header), log->fp); >>> + fflush(log->fp); >>> + >>> + fwts_log_section_begin_xml(log, "fwts"); >>> +} >>> + >>> +static void fwts_log_close_xml(fwts_log *log) >>> +{ >>> + fwts_log_section_end_xml(log); >>> + >>> + fwrite("\n", 1, 1, log->fp); >>> + fflush(log->fp); >>> +} >>> + >>> +fwts_log_ops fwts_log_xml_ops = { >>> + .vprintf = fwts_log_vprintf_xml, >>> + .underline = fwts_log_underline_xml, >>> + .newline = fwts_log_newline_xml, >>> + .section_begin = fwts_log_section_begin_xml, >>> + .section_end = fwts_log_section_end_xml, >>> + .open = fwts_log_open_xml, >>> + .close = fwts_log_close_xml >>> +}; >> >> >> Hi Colin, >> >> I've checked the xml file(results.log). It seems that it doesn't close >> properly (missing </tests> and </fwts>). >> Except that, all looks good to me. Thanks! Let me check why this is happening. Colin >> > > I formed another patch fixing this. >
On 01/06/12 09:21, Keng-Yu Lin wrote: > On Fri, Jun 1, 2012 at 10:43 AM, IvanHu <ivan.hu@canonical.com> wrote: >> On 05/28/2012 11:01 PM, Colin King wrote: >>> >>> From: Colin Ian King<colin.king@canonical.com> >>> >>> Signed-off-by: Colin Ian King<colin.king@canonical.com> >>> --- >>> doc/fwts.1 | 2 +- >>> src/lib/include/fwts_log.h | 1 + >>> src/lib/src/Makefile.am | 1 + >>> src/lib/src/fwts_framework.c | 4 +- >>> src/lib/src/fwts_log.c | 3 + >>> src/lib/src/fwts_log_xml.c | 186 >>> ++++++++++++++++++++++++++++++++++++++++++ >>> 6 files changed, 195 insertions(+), 2 deletions(-) >>> create mode 100644 src/lib/src/fwts_log_xml.c >>> >>> diff --git a/doc/fwts.1 b/doc/fwts.1 >>> index 0d773cd..09eee56 100644 >>> --- a/doc/fwts.1 >>> +++ b/doc/fwts.1 >>> @@ -150,7 +150,7 @@ specify the information in each log line. The >>> following specifiers are available >>> e.g. \-\-log\-format="%date %time [%field] (%owner): " >>> .TP >>> .B \-\-log\-type >>> -specify the log type. Currently plaintext and json log types are >>> available and the >>> +specify the log type. Currently plaintext, json and xml log types are >>> available and the >>> default is plaintext. >>> .TP >>> .B \-\-lp\-tags >>> diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h >>> index 8903bab..8027d41 100644 >>> --- a/src/lib/include/fwts_log.h >>> +++ b/src/lib/include/fwts_log.h >>> @@ -81,6 +81,7 @@ typedef struct fwts_log_ops_t { >>> >>> fwts_log_ops fwts_log_plaintext_ops; >>> fwts_log_ops fwts_log_json_ops; >>> +fwts_log_ops fwts_log_xml_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 cae1f91..acea9cb 100644 >>> --- a/src/lib/src/Makefile.am >>> +++ b/src/lib/src/Makefile.am >>> @@ -39,6 +39,7 @@ libfwts_la_SOURCES = \ >>> fwts_log.c \ >>> fwts_log_plaintext.c \ >>> fwts_log_json.c \ >>> + fwts_log_xml.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 1fcd88e..2b42982 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 or >>> json)." }, >>> + { "log-type", "", 1, "Specify log type (plaintext, >>> json or xml)." }, >>> { NULL, NULL, 0, NULL } >>> }; >>> >>> @@ -1040,6 +1040,8 @@ int fwts_framework_options_handler(fwts_framework >>> *fw, int argc, char * const ar >>> fw->log_type = LOG_TYPE_PLAINTEXT; >>> else if (!strcmp(optarg, "json")) >>> fw->log_type = LOG_TYPE_JSON; >>> + else if (!strcmp(optarg, "xml")) >>> + fw->log_type = LOG_TYPE_XML; >>> else { >>> fprintf(stderr, "--log-type can be either >>> plaintext or json.\n"); >>> return FWTS_ERROR; >>> diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c >>> index 5331fff..2b11441 100644 >>> --- a/src/lib/src/fwts_log.c >>> +++ b/src/lib/src/fwts_log.c >>> @@ -390,6 +390,9 @@ fwts_log *fwts_log_open(const char *owner, const char >>> *name, const char *mode, f >>> case LOG_TYPE_PLAINTEXT: >>> newlog->ops =&fwts_log_plaintext_ops; >>> break; >>> + case LOG_TYPE_XML: >>> + newlog->ops =&fwts_log_xml_ops; >>> + break; >>> case LOG_TYPE_NONE: >>> default: >>> newlog->ops =&fwts_log_plaintext_ops; >>> diff --git a/src/lib/src/fwts_log_xml.c b/src/lib/src/fwts_log_xml.c >>> new file mode 100644 >>> index 0000000..57b530b >>> --- /dev/null >>> +++ b/src/lib/src/fwts_log_xml.c >>> @@ -0,0 +1,186 @@ >>> +/* >>> + * 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<stdlib.h> >>> +#include<stdio.h> >>> +#include<stdarg.h> >>> +#include<string.h> >>> +#include<unistd.h> >>> +#include<sys/ioctl.h> >>> +#include<time.h> >>> + >>> +#include "fwts.h" >>> + >>> +#define MAX_XML_STACK (64) >>> +#define XML_INDENT (4) >>> + >>> +typedef struct { >>> + const char *name; >>> +} fwts_log_xml_stack_t; >>> + >>> +static fwts_log_xml_stack_t xml_stack[MAX_XML_STACK]; >>> +static int xml_stack_index = 0; >>> + >>> +/* >>> + * fwts_log_vprintf_xml() >>> + * vprintf to a log >>> + */ >>> +static int fwts_log_vprintf_xml(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) >>> +{ >>> + char buffer[4096]; >>> + struct tm tm; >>> + time_t now; >>> + char *str; >>> + >>> + 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); >>> + >>> + fprintf(log->fp, "%*s<logentry>\n", xml_stack_index * XML_INDENT, >>> ""); >>> + >>> + fprintf(log->fp, "%*s<line_num>%d</line_num>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", log->line_number); >>> + >>> + fprintf(log->fp, "%*s<date>%2.2d/%2.2d/%-2.2d</date>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100); >>> + >>> + fprintf(log->fp, "%*s<time>%2.2d:%2.2d:%2.2d</time>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", tm.tm_hour, tm.tm_min, tm.tm_sec); >>> + >>> + fprintf(log->fp, "%*s<field_type>%s</field_type>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", fwts_log_field_to_str_full(field)); >>> + >>> + str = fwts_log_level_to_str(level); >>> + if (!strcmp(str, " ")) >>> + str = "None"; >>> + >>> + fprintf(log->fp, "%*s<level>%s</level>\n", >>> + (xml_stack_index + 1) * XML_INDENT, "", str); >>> + >>> + fprintf(log->fp, "%*s<status>%s</status>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", *status ? status : "None"); >>> + >>> + fprintf(log->fp, "%*s<failure_label>%s</failure_label>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", label&& *label ? label : "None"); >>> >>> + >>> + vsnprintf(buffer, sizeof(buffer), fmt, args); >>> + fprintf(log->fp, "%*s<log_text>%s</log_text>\n", >>> + (xml_stack_index + 1) * XML_INDENT, >>> + "", buffer); >>> + >>> + fprintf(log->fp, "%*s</logentry>\n", xml_stack_index * XML_INDENT, >>> ""); >>> + fflush(log->fp); >>> + >>> + log->line_number++; >>> + >>> + return 0; >>> +} >>> + >>> +/* >>> + * fwts_log_underline_xml() >>> + * write an underline across log, using character ch as the underline >>> + */ >>> +static void fwts_log_underline_xml(fwts_log *log, const int ch) >>> +{ >>> + /* No-op for xml */ >>> +} >>> + >>> +/* >>> + * fwts_log_newline() >>> + * write newline to log >>> + */ >>> +static void fwts_log_newline_xml(fwts_log *log) >>> +{ >>> + /* No-op for xml */ >>> +} >>> + >>> +static void fwts_log_section_begin_xml(fwts_log *log, const char *name) >>> +{ >>> + xml_stack[xml_stack_index].name = name; >>> + >>> + fprintf(log->fp, "%*s<%s>\n", xml_stack_index * XML_INDENT, "", >>> name); >>> + fflush(log->fp); >>> + >>> + if (xml_stack_index< MAX_XML_STACK) >>> + xml_stack_index++; >>> + else { >>> + fprintf(stderr, "xml log stack overflow pushing section >>> %s.\n", name); >>> + exit(EXIT_FAILURE); >>> + } >>> +} >>> + >>> +static void fwts_log_section_end_xml(fwts_log *log) >>> +{ >>> + if (xml_stack_index> 0) { >>> + xml_stack_index--; >>> + fprintf(log->fp, "%*s</%s>\n", xml_stack_index * >>> XML_INDENT, >>> + "", xml_stack[xml_stack_index].name); >>> + fflush(log->fp); >>> + } else { >>> + fprintf(stderr, "xml log stack underflow.\n"); >>> + exit(EXIT_FAILURE); >>> + } >>> + >>> +} >>> + >>> +static void fwts_log_open_xml(fwts_log *log) >>> +{ >>> + char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\" >>> ?>\n"; >>> + >>> + fwrite(xml_header, 1, strlen(xml_header), log->fp); >>> + fflush(log->fp); >>> + >>> + fwts_log_section_begin_xml(log, "fwts"); >>> +} >>> + >>> +static void fwts_log_close_xml(fwts_log *log) >>> +{ >>> + fwts_log_section_end_xml(log); >>> + >>> + fwrite("\n", 1, 1, log->fp); >>> + fflush(log->fp); >>> +} >>> + >>> +fwts_log_ops fwts_log_xml_ops = { >>> + .vprintf = fwts_log_vprintf_xml, >>> + .underline = fwts_log_underline_xml, >>> + .newline = fwts_log_newline_xml, >>> + .section_begin = fwts_log_section_begin_xml, >>> + .section_end = fwts_log_section_end_xml, >>> + .open = fwts_log_open_xml, >>> + .close = fwts_log_close_xml >>> +}; >> >> >> Hi Colin, >> >> I've checked the xml file(results.log). It seems that it doesn't close >> properly (missing </tests> and </fwts>). >> Except that, all looks good to me. Thanks! I'm finding this tricky to reproduce. Can you tell me how you tested this so I can track down the offending bugs? Thanks! Colin >> > > I formed another patch fixing this. >
On Fri, Jun 1, 2012 at 4:58 PM, Colin Ian King <colin.king@canonical.com> wrote: > > I'm finding this tricky to reproduce. Can you tell me how you tested this so > I can track down the offending bugs? > > Thanks! > > Colin The attached result.log is an example of the xml log (with unmatched tags in the end). I pushed the my current working tree at http://kernel.ubuntu.com/git?p=lexical/fwts.git;a=shortlog;h=refs/heads/xml-test.
diff --git a/doc/fwts.1 b/doc/fwts.1 index 0d773cd..09eee56 100644 --- a/doc/fwts.1 +++ b/doc/fwts.1 @@ -150,7 +150,7 @@ specify the information in each log line. The following specifiers are available e.g. \-\-log\-format="%date %time [%field] (%owner): " .TP .B \-\-log\-type -specify the log type. Currently plaintext and json log types are available and the +specify the log type. Currently plaintext, json and xml log types are available and the default is plaintext. .TP .B \-\-lp\-tags diff --git a/src/lib/include/fwts_log.h b/src/lib/include/fwts_log.h index 8903bab..8027d41 100644 --- a/src/lib/include/fwts_log.h +++ b/src/lib/include/fwts_log.h @@ -81,6 +81,7 @@ typedef struct fwts_log_ops_t { fwts_log_ops fwts_log_plaintext_ops; fwts_log_ops fwts_log_json_ops; +fwts_log_ops fwts_log_xml_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 cae1f91..acea9cb 100644 --- a/src/lib/src/Makefile.am +++ b/src/lib/src/Makefile.am @@ -39,6 +39,7 @@ libfwts_la_SOURCES = \ fwts_log.c \ fwts_log_plaintext.c \ fwts_log_json.c \ + fwts_log_xml.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 1fcd88e..2b42982 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 or json)." }, + { "log-type", "", 1, "Specify log type (plaintext, json or xml)." }, { NULL, NULL, 0, NULL } }; @@ -1040,6 +1040,8 @@ int fwts_framework_options_handler(fwts_framework *fw, int argc, char * const ar fw->log_type = LOG_TYPE_PLAINTEXT; else if (!strcmp(optarg, "json")) fw->log_type = LOG_TYPE_JSON; + else if (!strcmp(optarg, "xml")) + fw->log_type = LOG_TYPE_XML; else { fprintf(stderr, "--log-type can be either plaintext or json.\n"); return FWTS_ERROR; diff --git a/src/lib/src/fwts_log.c b/src/lib/src/fwts_log.c index 5331fff..2b11441 100644 --- a/src/lib/src/fwts_log.c +++ b/src/lib/src/fwts_log.c @@ -390,6 +390,9 @@ fwts_log *fwts_log_open(const char *owner, const char *name, const char *mode, f case LOG_TYPE_PLAINTEXT: newlog->ops = &fwts_log_plaintext_ops; break; + case LOG_TYPE_XML: + newlog->ops = &fwts_log_xml_ops; + break; case LOG_TYPE_NONE: default: newlog->ops = &fwts_log_plaintext_ops; diff --git a/src/lib/src/fwts_log_xml.c b/src/lib/src/fwts_log_xml.c new file mode 100644 index 0000000..57b530b --- /dev/null +++ b/src/lib/src/fwts_log_xml.c @@ -0,0 +1,186 @@ +/* + * 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 <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <time.h> + +#include "fwts.h" + +#define MAX_XML_STACK (64) +#define XML_INDENT (4) + +typedef struct { + const char *name; +} fwts_log_xml_stack_t; + +static fwts_log_xml_stack_t xml_stack[MAX_XML_STACK]; +static int xml_stack_index = 0; + +/* + * fwts_log_vprintf_xml() + * vprintf to a log + */ +static int fwts_log_vprintf_xml(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) +{ + char buffer[4096]; + struct tm tm; + time_t now; + char *str; + + 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); + + fprintf(log->fp, "%*s<logentry>\n", xml_stack_index * XML_INDENT, ""); + + fprintf(log->fp, "%*s<line_num>%d</line_num>\n", + (xml_stack_index + 1) * XML_INDENT, + "", log->line_number); + + fprintf(log->fp, "%*s<date>%2.2d/%2.2d/%-2.2d</date>\n", + (xml_stack_index + 1) * XML_INDENT, + "", tm.tm_mday, tm.tm_mon + 1, (tm.tm_year+1900) % 100); + + fprintf(log->fp, "%*s<time>%2.2d:%2.2d:%2.2d</time>\n", + (xml_stack_index + 1) * XML_INDENT, + "", tm.tm_hour, tm.tm_min, tm.tm_sec); + + fprintf(log->fp, "%*s<field_type>%s</field_type>\n", + (xml_stack_index + 1) * XML_INDENT, + "", fwts_log_field_to_str_full(field)); + + str = fwts_log_level_to_str(level); + if (!strcmp(str, " ")) + str = "None"; + + fprintf(log->fp, "%*s<level>%s</level>\n", + (xml_stack_index + 1) * XML_INDENT, "", str); + + fprintf(log->fp, "%*s<status>%s</status>\n", + (xml_stack_index + 1) * XML_INDENT, + "", *status ? status : "None"); + + fprintf(log->fp, "%*s<failure_label>%s</failure_label>\n", + (xml_stack_index + 1) * XML_INDENT, + "", label && *label ? label : "None"); + + vsnprintf(buffer, sizeof(buffer), fmt, args); + fprintf(log->fp, "%*s<log_text>%s</log_text>\n", + (xml_stack_index + 1) * XML_INDENT, + "", buffer); + + fprintf(log->fp, "%*s</logentry>\n", xml_stack_index * XML_INDENT, ""); + fflush(log->fp); + + log->line_number++; + + return 0; +} + +/* + * fwts_log_underline_xml() + * write an underline across log, using character ch as the underline + */ +static void fwts_log_underline_xml(fwts_log *log, const int ch) +{ + /* No-op for xml */ +} + +/* + * fwts_log_newline() + * write newline to log + */ +static void fwts_log_newline_xml(fwts_log *log) +{ + /* No-op for xml */ +} + +static void fwts_log_section_begin_xml(fwts_log *log, const char *name) +{ + xml_stack[xml_stack_index].name = name; + + fprintf(log->fp, "%*s<%s>\n", xml_stack_index * XML_INDENT, "", name); + fflush(log->fp); + + if (xml_stack_index < MAX_XML_STACK) + xml_stack_index++; + else { + fprintf(stderr, "xml log stack overflow pushing section %s.\n", name); + exit(EXIT_FAILURE); + } +} + +static void fwts_log_section_end_xml(fwts_log *log) +{ + if (xml_stack_index > 0) { + xml_stack_index--; + fprintf(log->fp, "%*s</%s>\n", xml_stack_index * XML_INDENT, + "", xml_stack[xml_stack_index].name); + fflush(log->fp); + } else { + fprintf(stderr, "xml log stack underflow.\n"); + exit(EXIT_FAILURE); + } + +} + +static void fwts_log_open_xml(fwts_log *log) +{ + char *xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; + + fwrite(xml_header, 1, strlen(xml_header), log->fp); + fflush(log->fp); + + fwts_log_section_begin_xml(log, "fwts"); +} + +static void fwts_log_close_xml(fwts_log *log) +{ + fwts_log_section_end_xml(log); + + fwrite("\n", 1, 1, log->fp); + fflush(log->fp); +} + +fwts_log_ops fwts_log_xml_ops = { + .vprintf = fwts_log_vprintf_xml, + .underline = fwts_log_underline_xml, + .newline = fwts_log_newline_xml, + .section_begin = fwts_log_section_begin_xml, + .section_end = fwts_log_section_end_xml, + .open = fwts_log_open_xml, + .close = fwts_log_close_xml +};