From 7db3b0483da2a158f2559cd55f13ef7769e36d10 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Thu, 30 Jan 2014 11:04:31 -0800 Subject: [PATCH] Added XML Escape for junit reports. --- libtest/formatter.cc | 75 ++++++++++++++++++++++++++++++++++++---- m4/ax_compiler_vendor.m4 | 5 +-- m4/ax_restore_flags.m4 | 41 ++++++++++++++++------ m4/ax_save_flags.m4 | 60 ++++++++++++++++++++++++++------ 4 files changed, 152 insertions(+), 29 deletions(-) diff --git a/libtest/formatter.cc b/libtest/formatter.cc index 01c57609..ad5b1635 100644 --- a/libtest/formatter.cc +++ b/libtest/formatter.cc @@ -44,6 +44,54 @@ namespace libtest { +std::string& escape4XML(std::string const& arg, std::string& escaped_string) +{ + escaped_string.clear(); + + escaped_string+= '"'; + for (std::string::const_iterator x= arg.begin(), end= arg.end(); x != end; ++x) + { + unsigned char c= *x; + if (' ' <= c and c <= '~' and c != '\\' and c != '"' and c != '>' and c != '<') + { + escaped_string+= c; + } + else if (c == '>') + { + escaped_string+= '&'; + escaped_string+= 'g'; + escaped_string+= 't'; + escaped_string+= ';'; + } + else if (c == '<') + { + escaped_string+= '&'; + escaped_string+= 'l'; + escaped_string+= 't'; + escaped_string+= ';'; + } + else + { + escaped_string+= '\\'; + switch (c) { + case '"': escaped_string+= '"'; break; + case '\\': escaped_string+= '\\'; break; + case '\t': escaped_string+='t'; break; + case '\r': escaped_string+='r'; break; + case '\n': escaped_string+='n'; break; + default: + char const* const hexdig= "0123456789ABCDEF"; + escaped_string+= 'x'; + escaped_string+= hexdig[c >> 4]; + escaped_string+= hexdig[c & 0xF]; + } + } + } + escaped_string+= '"'; + + return escaped_string; +} + class TestCase { public: TestCase(const std::string& arg): @@ -110,7 +158,10 @@ TestCase* Formatter::current() void Formatter::skipped() { current()->result(TEST_SKIPPED); - Out << name() << "." << current()->name() << "\t\t\t\t\t" << "[ " << test_strerror(current()->result()) << " ]"; + Out << name() << "." + << current()->name() + << "\t\t\t\t\t" + << "[ " << test_strerror(current()->result()) << " ]"; reset(); } @@ -120,7 +171,9 @@ void Formatter::failed() assert(current()); current()->result(TEST_FAILURE); - Out << name() << "." << current()->name() << "\t\t\t\t\t" << "[ " << test_strerror(current()->result()) << " ]"; + Out << name() + << "." << current()->name() << "\t\t\t\t\t" + << "[ " << test_strerror(current()->result()) << " ]"; reset(); } @@ -129,6 +182,7 @@ void Formatter::success(const libtest::Timer& timer_) { assert(current()); current()->result(TEST_SUCCESS, timer_); + std::string escaped_string; Out << name() << "." << current()->name() @@ -141,20 +195,27 @@ void Formatter::success(const libtest::Timer& timer_) void Formatter::xml(libtest::Framework& framework_, std::ofstream& output) { - output << "" << std::endl; + std::string escaped_string; + + output << "" << std::endl; + for (Suites::iterator framework_iter= framework_.suites().begin(); framework_iter != framework_.suites().end(); ++framework_iter) { - output << "\tname() << "\" classname=\"\" package=\"\">" << std::endl; + output << "\t" + << std::endl; for (TestCases::iterator case_iter= (*framework_iter)->formatter()->testcases().begin(); case_iter != (*framework_iter)->formatter()->testcases().end(); ++case_iter) { - output << "\t\tname() - << "\" time=\"" + output << "\t\ttimer().elapsed_milliseconds() << "\">" << std::endl; diff --git a/m4/ax_compiler_vendor.m4 b/m4/ax_compiler_vendor.m4 index 13bf7dba..c2f421bc 100644 --- a/m4/ax_compiler_vendor.m4 +++ b/m4/ax_compiler_vendor.m4 @@ -4,7 +4,7 @@ # # SYNOPSIS # -# AX_COMPILER_VENDOR() +# AX_COMPILER_VENDOR # # DESCRIPTION # @@ -44,7 +44,7 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 11 +#serial 12 AC_DEFUN([AX_COMPILER_VENDOR], [AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, @@ -53,6 +53,7 @@ AC_DEFUN([AX_COMPILER_VENDOR], ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale: __PATHCC__,__PATHSCALE__ clang: __clang__ + fujitsu: __FUJITSU gnu: __GNUC__ sun: __SUNPRO_C,__SUNPRO_CC hp: __HP_cc,__HP_aCC diff --git a/m4/ax_restore_flags.m4 b/m4/ax_restore_flags.m4 index cf03cae7..aafd3638 100644 --- a/m4/ax_restore_flags.m4 +++ b/m4/ax_restore_flags.m4 @@ -4,28 +4,49 @@ # # SYNOPSIS # -# AX_RESTORE_FLAGS() +# AX_RESTORE_FLAGS([namespace]) # # DESCRIPTION # -# Restore common compilation flags from temporary variables +# Restore common compilation flags from temporary variables. +# +# Compilation flags includes: CPPFLAGS, CFLAGS, CXXFLAGS, LDFLAGS, LIBS, +# OBJCFLAGS. +# +# By default these flags are restored to a global (empty) namespace, but +# user could restore from specific NAMESPACE by using +# AX_RESTORE_FLAGS(NAMESPACE) macro. +# +# Typical usage is like: +# +# AX_SAVE_FLAGS(mypackage) +# CPPFLAGS="-Imypackagespath ${CPPFLAGS}" +# dnl ... do some detection ... +# AX_RESTORE_FLAGS(mypackage) # # LICENSE # # Copyright (c) 2009 Filippo Giunchedi +# Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University +# Copyright (c) 2011 Russ Allbery +# Copyright (c) 2013 Bastien ROUCARIES # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 3 +#serial 6 + +# save one flag in name space +AC_DEFUN([_AX_RESTORE_ONE_FLAG],[dnl + AS_VAR_PUSHDEF([_ax_restore_flag_var], [$2[]_$1[]_ax_save_flags]) + AS_VAR_COPY($2[],_ax_restore_flag_var) + AS_VAR_POPDEF([_ax_restore_flag_var]) +]) -AC_DEFUN([AX_RESTORE_FLAGS], [ - CPPFLAGS="${CPPFLAGS_save}" - CFLAGS="${CFLAGS_save}" - CXXFLAGS="${CXXFLAGS_save}" - OBJCFLAGS="${OBJCFLAGS_save}" - LDFLAGS="${LDFLAGS_save}" - LIBS="${LIBS_save}" +AC_DEFUN([AX_RESTORE_FLAGS], [dnl + m4_foreach([FLAG], dnl + [_AX_SAVE_FLAGS_LIST()], dnl + [_AX_RESTORE_ONE_FLAG([$1],FLAG)]) ]) diff --git a/m4/ax_save_flags.m4 b/m4/ax_save_flags.m4 index d2a05422..39f45be4 100644 --- a/m4/ax_save_flags.m4 +++ b/m4/ax_save_flags.m4 @@ -4,28 +4,68 @@ # # SYNOPSIS # -# AX_SAVE_FLAGS() +# AX_SAVE_FLAGS([NAMESPACE]) # # DESCRIPTION # -# Save common compilation flags into temporary variables +# Save common compilation flags into temporary variables. +# +# Compilation flags includes: CPPFLAGS, CFLAGS, CXXFLAGS, LDFLAGS, LIBS, +# OBJCFLAGS. +# +# By default these flags are saved to a global (empty) namespace, but user +# could specify a specific NAMESPACE to AX_SAVE_FLAGS macro and latter +# restore it by using AX_RESTORE_FLAGS(NAMESPACE). +# +# AX_SAVE_FLAGS(mypackage) +# CPPFLAGS="-Imypackagespath ${CPPFLAGS}" +# dnl .. do some detection ... +# AX_RESTORE_FLAGS(mypackage) # # LICENSE # # Copyright (c) 2009 Filippo Giunchedi +# Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University +# Copyright (c) 2011 Russ Allbery +# Copyright (c) 2013 Bastien ROUCARIES # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 3 +#serial 7 + +# list of flag to save +AC_DEFUN([_AX_SAVE_FLAGS_LIST],[dnl +[CCASFLAGS],dnl +[CFLAGS],dnl +[CPPFLAGS],dnl +[CXXFLAGS],dnl +[ERLCFLAGS],dnl +[FCFLAGS],dnl +[FCLIBS],dnl +[FFLAGS],dnl +[FLIBS],dnl +[GCJFLAGS],dnl +[JAVACFLAGS],dnl +[LDFLAGS],dnl +[LIBS],dnl +[OBJCFLAGS],dnl +[OBJCXXFLAGS],dnl +[UPCFLAGS],dnl +[VALAFLAGS]dnl +]) + +# save one flag in name space +AC_DEFUN([_AX_SAVE_ONE_FLAG],[ + AS_VAR_PUSHDEF([_ax_save_flag_var], [$2[]_$1[]_ax_save_flags]) + AS_VAR_COPY(_ax_save_flag_var, $2[]) + AS_VAR_POPDEF([_ax_save_flag_var]) +]) -AC_DEFUN([AX_SAVE_FLAGS], [ - CPPFLAGS_save="${CPPFLAGS}" - CFLAGS_save="${CFLAGS}" - CXXFLAGS_save="${CXXFLAGS}" - OBJCFLAGS_save="${OBJCFLAGS}" - LDFLAGS_save="${LDFLAGS}" - LIBS_save="${LIBS}" +AC_DEFUN([AX_SAVE_FLAGS],[dnl + m4_foreach([FLAG], dnl + [_AX_SAVE_FLAGS_LIST()], dnl + [_AX_SAVE_ONE_FLAG([$1],FLAG)]) ]) -- 2.30.2