Added XML Escape for junit reports.
authorBrian Aker <brian@tangent.org>
Thu, 30 Jan 2014 19:04:31 +0000 (11:04 -0800)
committerBrian Aker <brian@tangent.org>
Thu, 30 Jan 2014 19:04:31 +0000 (11:04 -0800)
libtest/formatter.cc
m4/ax_compiler_vendor.m4
m4/ax_restore_flags.m4
m4/ax_save_flags.m4

index 01c57609554ecc52d2f9ab036c7baf9cb6a770d0..ad5b163541b4f14a11e003431331f7facc79ea79 100644 (file)
   
 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 << "<testsuites name=\"" << framework_.name() << "\">" << std::endl;
+  std::string escaped_string;
+
+  output << "<testsuites name=" 
+    << escape4XML(framework_.name(), escaped_string) << ">" << std::endl;
+
   for (Suites::iterator framework_iter= framework_.suites().begin();
        framework_iter != framework_.suites().end();
        ++framework_iter)
   {
-    output << "\t<testsuite name=\"" << (*framework_iter)->name() << "\"  classname=\"\" package=\"\">" << std::endl;
+    output << "\t<testsuite name=" 
+      << escape4XML((*framework_iter)->name(), escaped_string)
+      << "  classname=\"\" package=\"\">" 
+      << std::endl;
 
     for (TestCases::iterator case_iter= (*framework_iter)->formatter()->testcases().begin();
          case_iter != (*framework_iter)->formatter()->testcases().end();
          ++case_iter)
     {
-      output << "\t\t<testcase name=\"
-        << (*case_iter)->name() 
-        << "\" time=\"" 
+      output << "\t\t<testcase name=" 
+        << escape4XML((*case_iter)->name(), escaped_string)
+        << " time=\"" 
         << (*case_iter)->timer().elapsed_milliseconds() 
         << "\">" 
         << std::endl;
index 13bf7dba19a0bdce207cb2aa14a32ed564676ed0..c2f421bc992a5a9f1123ad6a61df04e875c170a1 100644 (file)
@@ -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
index cf03cae790154a1f7d11b874925b488cbe57e310..aafd363865aa73e776837f0a947a35ca6cbfaed6 100644 (file)
@@ -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 <filippo@esaurito.net>
+#   Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University
+#   Copyright (c) 2011 Russ Allbery <rra@stanford.edu>
+#   Copyright (c) 2013 Bastien ROUCARIES <roucaries.bastien+autoconf@gmail.com>
 #
 #   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)])
 ])
index d2a054223b910e8da1815417b9488d17ed707105..39f45be46ebc3fbef54a5979e9762e2d95482287 100644 (file)
@@ -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 <filippo@esaurito.net>
+#   Copyright (c) 2011 The Board of Trustees of the Leland Stanford Junior University
+#   Copyright (c) 2011 Russ Allbery <rra@stanford.edu>
+#   Copyright (c) 2013 Bastien ROUCARIES <roucaries.bastien+autoconf@gmail.com>
 #
 #   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)])
 ])