[ros-ros] 01/04: Imported Upstream version 1.13.1

Jochen Sprickerhof jspricke-guest at moszumanska.debian.org
Sat Jun 18 15:58:50 UTC 2016


This is an automated email from the git hooks/post-receive script.

jspricke-guest pushed a commit to annotated tag debian/1.13.1-1
in repository ros-ros.

commit 272596403f46a70d16fb906d286bb320af4bcad3
Author: Jochen Sprickerhof <git at jochen.sprickerhof.de>
Date:   Sat Jun 18 11:29:37 2016 +0200

    Imported Upstream version 1.13.1
---
 core/mk/CHANGELOG.rst                  |   9 ++
 core/mk/package.xml                    |   2 +-
 core/rosbuild/CHANGELOG.rst            |   9 ++
 core/rosbuild/package.xml              |   2 +-
 core/roslang/CHANGELOG.rst             |   9 ++
 core/roslang/package.xml               |   2 +-
 core/roslib/CHANGELOG.rst              |  13 +++
 core/roslib/env-hooks/10.ros.bat.em    |   2 +-
 core/roslib/env-hooks/10.ros.sh.em     |   4 +-
 core/roslib/include/ros/package.h      |  39 +++++++-
 core/roslib/package.xml                |   2 +-
 core/roslib/src/package.cpp            |  19 +++-
 core/roslib/test/setup.cfg             |   6 --
 ros/package.xml                        |   2 +-
 tools/rosbash/CHANGELOG.rst            |  11 +++
 tools/rosbash/package.xml              |   2 +-
 tools/rosbash/rosbash                  |  18 ++++
 tools/rosbash/rosfish                  |   1 +
 tools/rosbash/rostcsh                  |   1 +
 tools/rosbash/roszsh                   |  19 +++-
 tools/rosboost_cfg/CHANGELOG.rst       |   9 ++
 tools/rosboost_cfg/package.xml         |   2 +-
 tools/rosclean/CHANGELOG.rst           |   9 ++
 tools/rosclean/package.xml             |   2 +-
 tools/rosclean/test/setup.cfg          |   4 -
 tools/roscreate/CHANGELOG.rst          |   9 ++
 tools/roscreate/package.xml            |   2 +-
 tools/roscreate/test/setup.cfg         |   4 -
 tools/rosmake/CHANGELOG.rst            |   9 ++
 tools/rosmake/package.xml              |   2 +-
 tools/rosmake/test/setup.cfg           |   4 -
 tools/rosunit/CHANGELOG.rst            |  12 +++
 tools/rosunit/package.xml              |   2 +-
 tools/rosunit/src/rosunit/junitxml.py  | 159 +++++++++++++++++++++------------
 tools/rosunit/src/rosunit/pyunit.py    |   9 +-
 tools/rosunit/src/rosunit/xmlrunner.py |  88 ++++++++++--------
 tools/rosunit/test/dotname_cases.py    |  36 ++++++++
 tools/rosunit/test/setup.cfg           |   4 -
 tools/rosunit/test/test_dotname.py     |  48 ++++++++++
 tools/rosunit/test/test_junitxml.py    |  38 ++++++++
 40 files changed, 488 insertions(+), 136 deletions(-)

diff --git a/core/mk/CHANGELOG.rst b/core/mk/CHANGELOG.rst
index 6cae18e..1b4b09a 100644
--- a/core/mk/CHANGELOG.rst
+++ b/core/mk/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package mk
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/core/mk/package.xml b/core/mk/package.xml
index dc1aa7f..911ebce 100644
--- a/core/mk/package.xml
+++ b/core/mk/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>mk</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
     A collection of .mk include files for building ROS architectural elements.
     Most package authors should use cmake .mk, which calls CMake for the build of the package.
diff --git a/core/rosbuild/CHANGELOG.rst b/core/rosbuild/CHANGELOG.rst
index 28de4ae..9053b64 100644
--- a/core/rosbuild/CHANGELOG.rst
+++ b/core/rosbuild/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package rosbuild
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/core/rosbuild/package.xml b/core/rosbuild/package.xml
index 74921d4..2869f4a 100644
--- a/core/rosbuild/package.xml
+++ b/core/rosbuild/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosbuild</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
     rosbuild contains scripts for managing the CMake-based build system for ROS.
   </description>
diff --git a/core/roslang/CHANGELOG.rst b/core/roslang/CHANGELOG.rst
index b030733..ec35cdd 100644
--- a/core/roslang/CHANGELOG.rst
+++ b/core/roslang/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package roslang
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/core/roslang/package.xml b/core/roslang/package.xml
index fee414b..3832a6a 100644
--- a/core/roslang/package.xml
+++ b/core/roslang/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>roslang</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
     roslang is a common package that all <a href="http://www.ros.org/wiki/Client%20Libraries">ROS client libraries</a> depend on.
     This is mainly used to find client libraries (via 'rospack depends-on1 roslang').
diff --git a/core/roslib/CHANGELOG.rst b/core/roslib/CHANGELOG.rst
index 2e0d92e..7ba808b 100644
--- a/core/roslib/CHANGELOG.rst
+++ b/core/roslib/CHANGELOG.rst
@@ -2,6 +2,19 @@
 Changelog for package roslib
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+* update ROS_DISTRO to kinetic
+
+1.12.6 (2016-03-10)
+-------------------
+* expose an API (ros::package::getPlugins) which can map multiple export values to one package name (`#103 <https://github.com/ros/ros/issues/103>`_)
+* deprecate API returning incomplete information (`#103 <https://github.com/ros/ros/issues/103>`_)
+* allow caching of rospack results (`#97 <https://github.com/ros/ros/issues/97>`_)
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/core/roslib/env-hooks/10.ros.bat.em b/core/roslib/env-hooks/10.ros.bat.em
index 03b04fb..62b818c 100644
--- a/core/roslib/env-hooks/10.ros.bat.em
+++ b/core/roslib/env-hooks/10.ros.bat.em
@@ -5,7 +5,7 @@ set _COMMAND=@(PYTHON_EXECUTABLE) -c "import os; print(os.pathsep.join([x for x
 rem Need the delims= line here to ensure that it reads with eol delimiters, not space.
 for /f "delims=" %%i in ('%COMMAND%') do set PATH=%%i
 
-set ROS_DISTRO=jade
+set ROS_DISTRO=kinetic
 
 REM python function to generate ROS package path based on all parent workspaces (prepends the separator if necessary)
 REM do not use EnableDelayedExpansion here, it messes with the != symbols
diff --git a/core/roslib/env-hooks/10.ros.sh.em b/core/roslib/env-hooks/10.ros.sh.em
index 7a65047..139246b 100644
--- a/core/roslib/env-hooks/10.ros.sh.em
+++ b/core/roslib/env-hooks/10.ros.sh.em
@@ -3,10 +3,10 @@
 # scrub old ROS bin dirs, to avoid accidentally finding the wrong executables
 export PATH="`@(PYTHON_EXECUTABLE) -c \"import os; print(os.pathsep.join([x for x in \\\"$PATH\\\".split(os.pathsep) if not any([d for d in ['cturtle', 'diamondback', 'electric', 'fuerte'] if d in x])]))\"`"
 
-if [ -n "$ROS_DISTRO" -a "$ROS_DISTRO" != "jade" ]; then
+if [ -n "$ROS_DISTRO" -a "$ROS_DISTRO" != "kinetic" ]; then
   echo "ROS_DISTRO was set to '$ROS_DISTRO' before. Please make sure that the environment does not mix paths from different distributions."
 fi
-export ROS_DISTRO=jade
+export ROS_DISTRO=kinetic
 
 # python function to generate ROS package path based on all workspaces
 PYTHON_CODE_BUILD_ROS_PACKAGE_PATH=$(cat <<EOF
diff --git a/core/roslib/include/ros/package.h b/core/roslib/include/ros/package.h
index 5287f6d..6fd9206 100644
--- a/core/roslib/include/ros/package.h
+++ b/core/roslib/include/ros/package.h
@@ -29,6 +29,7 @@
 #define ROSLIB_PACKAGE_H
 
 #include <string>
+#include <utility>
 #include <vector>
 #include <map>
 
@@ -108,10 +109,42 @@ ROSLIB_DECL bool getAll(V_string& packages);
 ROSLIB_DECL void getPlugins(const std::string& package, const std::string& attribute, V_string& plugins, bool force_recrawl=false);
 
 /**
- * \brief Call the "rospack plugins" command, eg. "rospack plugins --attrib=<attribute> <package>".  Returns a map of package name to
- * export value.
+ * \brief Call the "rospack plugins" command, eg. "rospack plugins --attrib=<attribute> <name>".
+ * Return a vector of string pairs which are package names and exported values respectively.
+ * Note that there can be multiple values for any single package.
+ *
+ * Note that while this uses the original rospack 'plugin' terminology,
+ * this effectively works for any exported tag with attributes in the
+ * catkin package.xml export list. Typical examples include:
+ *
+\code{.xml}
+<export>
+  <nav_core plugin="${prefix}/blp_plugin.xml" />  <!-- name="nav_core", attribute="plugin" -->
+  <rosdoc config="rosdoc.yaml" />                 <!-- name="rosdoc",   attribute="config" -->
+</export>
+\endcode
+ *
+ * \param name : name of the package export tag (has to be a package name) [in]
+ * \param attribute : name of the attribute inside the export tag with which to filter results [in]
+ * \param exports : package/value export pairs resulting from the search [out]
+ * \param force_recrawl : force rospack to rediscover everything on the system before running the search [in]
+ */
+ROSLIB_DECL void getPlugins(
+  const std::string& name,
+  const std::string& attribute,
+  std::vector<std::pair<std::string, std::string> >& exports,
+  bool force_recrawl=false
+);
+
+/**
+ * \brief Call the "rospack plugins" command, eg. "rospack plugins --attrib=<attribute> <package>".
+ * Return a map of package name to export value.
+ *
+ * \warning If there are multiple export values, only the last one is saved in the map.
+ *
+ * \deprecated Prefer the ::getPlugins(const std::string&, const std::string&, std::vector<std::pair<std::string, std::string>>&, bool) api instead.
  */
-ROSLIB_DECL void getPlugins(const std::string& package, const std::string& attribute, M_string& plugins, bool force_recrawl=false);
+ROS_DEPRECATED ROSLIB_DECL void getPlugins(const std::string& package, const std::string& attribute, M_string& plugins, bool force_recrawl=false);
 
 } // namespace package
 } // namespace ros
diff --git a/core/roslib/package.xml b/core/roslib/package.xml
index 734ce4c..ee9693d 100644
--- a/core/roslib/package.xml
+++ b/core/roslib/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>roslib</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
     Base dependencies and support libraries for ROS.
     roslib contains many of the common data structures and tools that are shared across ROS client library implementations.
diff --git a/core/roslib/src/package.cpp b/core/roslib/src/package.cpp
index 7bdd4bf..37fd3e7 100644
--- a/core/roslib/src/package.cpp
+++ b/core/roslib/src/package.cpp
@@ -47,8 +47,8 @@ static boost::mutex librospack_mutex;
 std::string command(const std::string& _cmd)
 {
   boost::mutex::scoped_lock lock(librospack_mutex);
-
-  rospack::ROSPack rp;
+  // static allows caching of results in between calls (in same process)
+  static rospack::ROSPack rp;
   int ret;
   try
   {
@@ -134,6 +134,21 @@ static void getPlugins(const std::string& package, const std::string& attribute,
   }
 }
 
+void getPlugins(
+  const std::string& name,
+  const std::string& attribute,
+  std::vector<std::pair<std::string, std::string> >& exports,
+  bool force_recrawl
+)
+{
+  V_string packages, plugins;
+  getPlugins(name, attribute, packages, plugins, force_recrawl);
+  // works on the assumption the previous call always return equal length package/plugin lists
+  for (std::size_t i = 0; i < packages.size(); ++i ) {
+    exports.push_back(std::pair<std::string, std::string>(packages[i], plugins[i]));
+  }
+}
+
 void getPlugins(const std::string& package, const std::string& attribute, V_string& plugins, bool force_recrawl)
 {
   V_string packages;
diff --git a/core/roslib/test/setup.cfg b/core/roslib/test/setup.cfg
deleted file mode 100644
index 9c1b3ec..0000000
--- a/core/roslib/test/setup.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-[nosetests]
-with-xunit=1
-with-coverage=1
-cover-package=roslib
-tests=test_roslib_manifest.py,test_roslib_names.py,test_roslib_packages.py,test_roslib.py, test_roslib_rosenv.py, test_roslib_stack_manifest.py, test_roslib_stacks.py, test_roslib_exceptions.py, test_roslib_manifestlib.py
-
diff --git a/ros/package.xml b/ros/package.xml
index 39873a5..9e656a9 100644
--- a/ros/package.xml
+++ b/ros/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>ros</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>ROS packaging system</description>
   <maintainer email="dthomas at osrfoundation.org">Dirk Thomas</maintainer>
   <license>BSD</license>
diff --git a/tools/rosbash/CHANGELOG.rst b/tools/rosbash/CHANGELOG.rst
index 7c6f6b2..9635db1 100644
--- a/tools/rosbash/CHANGELOG.rst
+++ b/tools/rosbash/CHANGELOG.rst
@@ -2,6 +2,17 @@
 Changelog for package rosbash
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+* add roscat to display file contents (`#99 <https://github.com/ros/ros/pull/99>`_)
+* roszsh: Ignore hidden files and directory in completion (`#100 <https://github.com/ros/ros/pull/100>`_)
+
 1.12.5 (2015-10-13)
 -------------------
 * rosrun: allow spaces in command names and search paths (`#94 <https://github.com/ros/ros/pull/94>`_)
diff --git a/tools/rosbash/package.xml b/tools/rosbash/package.xml
index 4af582d..2642ea2 100644
--- a/tools/rosbash/package.xml
+++ b/tools/rosbash/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosbash</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
     Assorted shell commands for using ros with bash.
   </description>
diff --git a/tools/rosbash/rosbash b/tools/rosbash/rosbash
index 4d58307..be7ddb6 100644
--- a/tools/rosbash/rosbash
+++ b/tools/rosbash/rosbash
@@ -282,6 +282,23 @@ function roscp {
     cp ${arg} ${3}
 }
 
+function roscat {
+    local arg
+    if [[ $1 = "--help" ]] || [[ $# -ne 2 ]]; then
+       echo -e "usage: roscat [package] [file]\n\nDisplay a file content within a package."
+       [[ $1 = "--help" ]] && return 0 || return 1
+    fi
+    _roscmd ${1} ${2}
+    [ $? -eq 1 ] && return 1
+    if [[ -n ${arg} ]]; then
+        if [[ -z $CATTER ]]; then
+            cat ${arg}
+        else
+            $CATTER ${arg}
+        fi
+    fi
+}
+
 function rosawesome {
    alias megamaid='rosbag record'
    alias suck2blow='rosbag play'
@@ -949,6 +966,7 @@ complete -F "_roscomplete_rosclean" "rosclean"
 complete -F "_roscomplete_exe" "rosrun"
 complete -F "_roscomplete_file" "rosed"
 complete -F "_roscomplete_file" "roscp"
+complete -F "_roscomplete_file" "roscat"
 complete -F "_roscomplete_launch" -o filenames "roslaunch"
 complete -F "_roscomplete_test" -o filenames "rostest"
 complete -F "_roscomplete_rospack" "rospack"
diff --git a/tools/rosbash/rosfish b/tools/rosbash/rosfish
index 18b0983..87ac808 100644
--- a/tools/rosbash/rosfish
+++ b/tools/rosbash/rosfish
@@ -1,3 +1,4 @@
+#alias roscat 'echo "unimplemented"'
 
 function _rossed
     if test (uname) = "Darwin" -o (uname) = "FreeBSD"
diff --git a/tools/rosbash/rostcsh b/tools/rosbash/rostcsh
index 1968364..aabaab9 100644
--- a/tools/rosbash/rostcsh
+++ b/tools/rosbash/rostcsh
@@ -4,6 +4,7 @@ alias rosls 'ls `rospack find \!*`'
 #alias rosd 'echo "unimplemented"'
 #alias rospd 'echo "unimplemented"'
 #alias rosed 'echo "unimplemented"'
+#alias roscat 'echo "unimplemented"'
 #alias roscmd 'echo "unimplemented"'
 #alias roscp 'echo "unimplemented"'
 
diff --git a/tools/rosbash/roszsh b/tools/rosbash/roszsh
index ba4b9e8..a02a0e3 100644
--- a/tools/rosbash/roszsh
+++ b/tools/rosbash/roszsh
@@ -263,6 +263,21 @@ function roscp {
     cp ${arg} ${3}
 }
 
+function roscat {
+    local arg
+    if [[ $1 = "--help" ]] | [[ $# -ne 2 ]]; then
+        echo -e "usage: roscat [package] [file]\n\nDisplay a file content within a package."
+        [[ $1 = "--help" ]] && return 0 || return 1
+    fi
+    _roscmd ${1} ${2}
+    [ $? -eq 1 ] && return 1
+    if [[ -z $CATTER ]]; then
+        cat ${arg}
+    else
+        $CATTER ${arg}
+    fi
+}
+
 function _roscomplete {
     local arg opts stack_opts
     reply=()
@@ -344,7 +359,7 @@ function _roscomplete_exe {
     else
         perm="/111"
     fi
-    _roscomplete_search_dir "-type f -perm $perm -regex .*/.*$"
+    _roscomplete_search_dir "-type f -perm $perm -regex .*/.*$ ! -path */\.*"
 }
 
 function _roscomplete_file {
@@ -730,7 +745,7 @@ compctl -K "_roscomplete_sub_dir" -S / "roscd" "rospd" "rosls"
 compctl -K "_roscomplete_rosmake" "rosmake"
 
 compctl -x 'p[1]' -k "(check purge)" -- "rosclean"
-compctl -f -x 'p[1]' -K "_roscomplete" - 'p[2]' -K _roscomplete_file -- "rosed" "roscp"
+compctl -f -x 'p[1]' -K "_roscomplete" - 'p[2]' -K _roscomplete_file -- "rosed" "roscp" "roscat"
 compctl -f -x 'S[-]' -k '(--debug --prefix)' - 'c[-1,--prefix][-1,-p]' -h '' - 'p[1],c[-1,-d],c[-1,--debug],c[-2,-p],c[-2,--prefix]' -K "_roscomplete" - 'p[2],c[-2,-d],c[-2,--debug],c[-3,-p],c[-3,--prefix]' -K _roscomplete_exe -- "rosrun"
 compctl -/g '*.(launch|test)' -x 'p[1]' -K "_roscomplete" -tx - 'p[2]' -K _roscomplete_launchfile -- + -x 'S[--]' -k "(--files --args --nodes --find-node --child --local --screen --server_uri --run_id --wait --port --core --pid --dump-params)" -- "roslaunch"
 compctl -/g '*.(launch|test)' -x 'p[1]' -K "_roscomplete" -tx - 'p[2]' -K _roscomplete_launchfile -- + -x 'S[--]' -k "(--bare --bare-limit --bare-name --pkgdir --package)" -- "rostest"
diff --git a/tools/rosboost_cfg/CHANGELOG.rst b/tools/rosboost_cfg/CHANGELOG.rst
index 2bdb52f..8b81c6e 100644
--- a/tools/rosboost_cfg/CHANGELOG.rst
+++ b/tools/rosboost_cfg/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package rosboost_cfg
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/tools/rosboost_cfg/package.xml b/tools/rosboost_cfg/package.xml
index d6f06ce..9ec695e 100644
--- a/tools/rosboost_cfg/package.xml
+++ b/tools/rosboost_cfg/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosboost_cfg</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
     Contains scripts used by the rosboost-cfg tool for determining cflags/lflags/etc. of boost on your system
   </description>
diff --git a/tools/rosclean/CHANGELOG.rst b/tools/rosclean/CHANGELOG.rst
index 71367d6..898c661 100644
--- a/tools/rosclean/CHANGELOG.rst
+++ b/tools/rosclean/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package rosclean
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/tools/rosclean/package.xml b/tools/rosclean/package.xml
index 9d46055..e96e259 100644
--- a/tools/rosclean/package.xml
+++ b/tools/rosclean/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosclean</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
     rosclean: cleanup filesystem resources (e.g. log files).
   </description>
diff --git a/tools/rosclean/test/setup.cfg b/tools/rosclean/test/setup.cfg
deleted file mode 100644
index 83918b1..0000000
--- a/tools/rosclean/test/setup.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-[nosetests]
-with-coverage=1
-cover-package=rosclean
-with-xunit=1
diff --git a/tools/roscreate/CHANGELOG.rst b/tools/roscreate/CHANGELOG.rst
index 3b46ac2..bd9b051 100644
--- a/tools/roscreate/CHANGELOG.rst
+++ b/tools/roscreate/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package roscreate
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/tools/roscreate/package.xml b/tools/roscreate/package.xml
index 995f09c..e57d2e9 100644
--- a/tools/roscreate/package.xml
+++ b/tools/roscreate/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>roscreate</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
      roscreate contains a tool that assists in the creation of ROS filesystem resources.
      It provides: <tt>roscreate-pkg</tt>, which creates a new package directory,
diff --git a/tools/roscreate/test/setup.cfg b/tools/roscreate/test/setup.cfg
deleted file mode 100644
index 7ae7ae0..0000000
--- a/tools/roscreate/test/setup.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-[nosetests]
-with-coverage=1
-cover-package=roscreate
-with-xunit=1
diff --git a/tools/rosmake/CHANGELOG.rst b/tools/rosmake/CHANGELOG.rst
index fed3aa9..cf1ff11 100644
--- a/tools/rosmake/CHANGELOG.rst
+++ b/tools/rosmake/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog for package rosmake
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/tools/rosmake/package.xml b/tools/rosmake/package.xml
index 2e4ac4a..55e9663 100644
--- a/tools/rosmake/package.xml
+++ b/tools/rosmake/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosmake</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
      rosmake is a ros dependency aware build tool which can be used to
      build all dependencies in the correct order.
diff --git a/tools/rosmake/test/setup.cfg b/tools/rosmake/test/setup.cfg
deleted file mode 100644
index 4b6998d..0000000
--- a/tools/rosmake/test/setup.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-[nosetests]
-with-coverage=1
-cover-package=rosmake
-with-xunit=1
diff --git a/tools/rosunit/CHANGELOG.rst b/tools/rosunit/CHANGELOG.rst
index 0f92b36..802f63f 100644
--- a/tools/rosunit/CHANGELOG.rst
+++ b/tools/rosunit/CHANGELOG.rst
@@ -2,6 +2,18 @@
 Changelog for package rosunit
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+1.13.1 (2016-03-13)
+-------------------
+* fix a regression in XML reports introduced in 1.12.6 (`#109 <https://github.com/ros/ros/pull/109>`_)
+
+1.13.0 (2016-03-10)
+-------------------
+
+1.12.6 (2016-03-10)
+-------------------
+* remove invalid characters from XML unit test results (`#89 <https://github.com/ros/ros/pull/89>`_, `#108 <https://github.com/ros/ros/pull/108>`_)
+* add ability to load tests using dotnames in rosunit (`#101 <https://github.com/ros/ros/issues/101>`_)
+
 1.12.5 (2015-10-13)
 -------------------
 
diff --git a/tools/rosunit/package.xml b/tools/rosunit/package.xml
index ce6f5d4..3e853ba 100644
--- a/tools/rosunit/package.xml
+++ b/tools/rosunit/package.xml
@@ -1,6 +1,6 @@
 <package>
   <name>rosunit</name>
-  <version>1.12.5</version>
+  <version>1.13.1</version>
   <description>
      Unit-testing package for ROS. This is a lower-level library for rostest and handles unit tests, whereas rostest handles integration tests.
   </description>
diff --git a/tools/rosunit/src/rosunit/junitxml.py b/tools/rosunit/src/rosunit/junitxml.py
index fee2a19..ca3bf60 100644
--- a/tools/rosunit/src/rosunit/junitxml.py
+++ b/tools/rosunit/src/rosunit/junitxml.py
@@ -49,12 +49,22 @@ import string
 import codecs
 import re
 
+import xml.etree.ElementTree as ET
 from xml.dom.minidom import parse, parseString
 from xml.dom import Node as DomNode
 
 from functools import reduce
 import rospkg
 
+invalid_chars = re.compile(ur'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\xFF\u0100-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]')
+def invalid_char_replacer(m):
+    return "&#x"+('%04X' % ord(m.group(0)))+";"
+def filter_nonprintable_text(text):
+    return re.sub(invalid_chars, invalid_char_replacer, text)
+
+def cdata(cdata_text):
+    return '<![CDATA[\n{}\n]]>'.format(cdata_text)
+
 class TestInfo(object):
     """
     Common container for 'error' and 'failure' results
@@ -75,25 +85,42 @@ class TestError(TestInfo):
     'error' result container        
     """
     def xml(self):
-        data = '<error type="%s"><![CDATA[%s]]></error>' % (self.type, self.text)
-        try:
-            data = unicode(data)
-        except NameError:
-            pass
-        return data
+        """
+        @return XML tag representing the object, with non-XML text filtered out
+        @rtype: str
+        """
+        return ET.tostring(self.xml_element(), encoding='utf-8', method='xml')
+
+    def xml_element(self):
+        """
+        @return XML tag representing the object, with non-XML text filtered out
+        @rtype: xml.etree.ElementTree.Element
+        """
+        error = ET.Element('error')
+        error.set('type', self.type)
+        error.text = cdata(filter_nonprintable_text(self.text))
+        return error
 
 class TestFailure(TestInfo):
     """
     'failure' result container        
     """
     def xml(self):
-        data = '<failure type="%s"><![CDATA[%s]]></failure>' % (self.type, self.text)
-        try:
-            data = unicode(data)
-        except NameError:
-            pass
-        return data
+        """
+        @return XML tag representing the object, with non-XML text filtered out
+        @rtype: str
+        """
+        return ET.tostring(self.xml_element(), encoding='utf-8', method='xml')
 
+    def xml_element(self):
+        """
+        @return XML tag representing the object, with non-XML text filtered out
+        @rtype: xml.etree.ElementTree.Element
+        """
+        error = ET.Element('failure')
+        error.set('type', self.type)
+        error.text = cdata(filter_nonprintable_text(self.text))
+        return error
 
 class TestCaseResult(object):
     """
@@ -169,15 +196,26 @@ class TestCaseResult(object):
         self.errors.append(error)
 
     def xml(self):
-        data = '  <testcase classname="%s" name="%s" time="%s">\n' % (self.classname, self.name, self.time) + \
-               '\n    '.join([f.xml() for f in self.failures]) + \
-               '\n    '.join([e.xml() for e in self.errors]) + \
-               '  </testcase>'
-        try:
-            data = unicode(data)
-        except NameError:
-            pass
-        return data
+        """
+        @return XML tag representing the object, with non-XML text filtered out
+        @rtype: str
+        """
+        return ET.tostring(self.xml_element(), encoding='utf-8', method='xml')
+
+    def xml_element(self):
+        """
+        @return XML tag representing the object, with non-XML text filtered out
+        @rtype: xml.etree.ElementTree.Element
+        """
+        testcase = ET.Element('testcase')
+        testcase.set('classname', self.classname)
+        testcase.set('name', self.name)
+        testcase.set('time', str(self.time))
+        for f in self.failures:
+            testcase.append(f.xml_element())
+        for e in self.errors:
+            testcase.append(e.xml_element())
+        return testcase
         
 class Result(object):
     __slots__ = ['name', 'num_errors', 'num_failures', 'num_tests', \
@@ -216,22 +254,23 @@ class Result(object):
         """
         self.test_case_results.append(r)
 
-    def xml(self):
+    def xml_element(self):
         """
         @return: document as unicode (UTF-8 declared) XML according to Ant JUnit spec
         """
-        data = '<?xml version="1.0" encoding="utf-8"?>' + \
-               '<testsuite name="%s" tests="%s" errors="%s" failures="%s" time="%s">' % \
-               (self.name, self.num_tests, self.num_errors, self.num_failures, self.time) + \
-               '\n'.join([tc.xml() for tc in self.test_case_results]) + \
-               '  <system-out><![CDATA[%s]]></system-out>' % self.system_out + \
-               '  <system-err><![CDATA[%s]]></system-err>' % self.system_err + \
-               '</testsuite>'
-        try:
-            data = unicode(data)
-        except NameError:
-            pass
-        return data
+        testsuite = ET.Element('testsuite')
+        testsuite.set('tests', str(self.num_tests))
+        testsuite.set('failures', str(self.num_failures))
+        testsuite.set('time', str(self.time))
+        testsuite.set('errors', str(self.num_errors))
+        testsuite.set('name', self.name)
+        for tc in self.test_case_results:
+            tc.xml(testsuite) 
+        system_out = ET.SubElement(testsuite, 'system-out')
+        system_out.text = cdata(filter_nonprintable_text(self.system_out))
+        system_err = ET.SubElement(testsuite, 'system-err')
+        system_err.text = cdata(filter_nonprintable_text(self.system_err))
+        return ET.tostring(testsuite, encoding='utf-8', method='xml')
 
 def _text(tag):
     return reduce(lambda x, y: x + y, [c.data for c in tag.childNodes if c.nodeType in [DomNode.TEXT_NODE, DomNode.CDATA_SECTION_NODE]], "").strip()
@@ -426,23 +465,24 @@ def test_failure_junit_xml(test_name, message, stdout=None):
     @param stdout: stdout data to include in report
     @type  stdout: str
     """
-    if not stdout:
-      return """<?xml version="1.0" encoding="UTF-8"?>
-<testsuite tests="1" failures="1" time="1" errors="0" name="%s">
-  <testcase name="test_ran" status="run" time="1" classname="Results">
-  <failure message="%s" type=""/>
-  </testcase>
-</testsuite>"""%(test_name, message)
-    else:
-      return """<?xml version="1.0" encoding="UTF-8"?>
-<testsuite tests="1" failures="1" time="1" errors="0" name="%s">
-  <testcase name="test_ran" status="run" time="1" classname="Results">
-  <failure message="%s" type=""/>
-  </testcase>
-  <system-out><![CDATA[[
-%s
-]]></system-out>
-</testsuite>"""%(test_name, message, stdout)
+    testsuite = ET.Element('testsuite')
+    testsuite.set('tests', '1')
+    testsuite.set('failures', '1')
+    testsuite.set('time', '1')
+    testsuite.set('errors', '0')
+    testsuite.set('name', test_name)
+    testcase = ET.SubElement(testsuite, 'testcase')
+    testcase.set('name', 'test_ran')
+    testcase.set('status', 'run')
+    testcase.set('time', '1')
+    testcase.set('classname', 'Results')
+    failure = ET.SubElement(testcase, 'failure')
+    failure.set('message', message)
+    failure.set('type', '')
+    if stdout:
+        system_out = ET.SubElement(testsuite, 'system-out')
+        system_out.text = cdata(filter_nonprintable_text(stdout))
+    return ET.tostring(testsuite, encoding='utf-8', method='xml')
 
 def test_success_junit_xml(test_name):
     """
@@ -451,11 +491,18 @@ def test_success_junit_xml(test_name):
     @param test_name: Name of test that passed
     @type  test_name: str
     """
-    return """<?xml version="1.0" encoding="UTF-8"?>
-<testsuite tests="1" failures="0" time="1" errors="0" name="%s">
-  <testcase name="test_ran" status="run" time="1" classname="Results">
-  </testcase>
-</testsuite>"""%(test_name)
+    testsuite = ET.Element('testsuite')
+    testsuite.set('tests', '1')
+    testsuite.set('failures', '0')
+    testsuite.set('time', '1')
+    testsuite.set('errors', '0')
+    testsuite.set('name', test_name)
+    testcase = ET.SubElement(testsuite, 'testcase')
+    testcase.set('name', 'test_ran')
+    testcase.set('status', 'run')
+    testcase.set('time', '1')
+    testcase.set('classname', 'Results')
+    return ET.tostring(testsuite, encoding='utf-8', method='xml')
 
 def print_summary(junit_results, runner_name='ROSUNIT'):
     """
diff --git a/tools/rosunit/src/rosunit/pyunit.py b/tools/rosunit/src/rosunit/pyunit.py
index ed12a5e..65cbf4f 100644
--- a/tools/rosunit/src/rosunit/pyunit.py
+++ b/tools/rosunit/src/rosunit/pyunit.py
@@ -57,6 +57,8 @@ def unitrun(package, test_name, test, sysargs=None, coverage_packages=None):
     
     @param package: name of ROS package that is running the test
     @type  package: str
+    @param test: a test case instance or a name resolving to a test case or suite
+    @type  test: unittest.TestCase, or string
     @param coverage_packages: list of Python package to compute coverage results for. Defaults to package
     @type  coverage_packages: [str]
     @param sysargs: (optional) alternate sys.argv
@@ -84,7 +86,12 @@ def unitrun(package, test_name, test, sysargs=None, coverage_packages=None):
         start_coverage(coverage_packages)
 
     # create and run unittest suite with our xmllrunner wrapper
-    suite = unittest.TestLoader().loadTestsFromTestCase(test)
+    suite = None
+    if issubclass(test, unittest.TestCase):
+        suite = unittest.TestLoader().loadTestsFromTestCase(test)
+    else:
+        suite = unittest.TestLoader().loadTestsFromName(test)
+
     if text_mode:
         result = unittest.TextTestRunner(verbosity=2).run(suite)
     else:
diff --git a/tools/rosunit/src/rosunit/xmlrunner.py b/tools/rosunit/src/rosunit/xmlrunner.py
index ee11ba6..dc1b567 100644
--- a/tools/rosunit/src/rosunit/xmlrunner.py
+++ b/tools/rosunit/src/rosunit/xmlrunner.py
@@ -20,7 +20,10 @@ try:
 except ImportError:
     from io import StringIO
 from xml.sax.saxutils import escape
+import xml.etree.ElementTree as ET
 
+def cdata(cdata_text):
+    return '<![CDATA[\n{}\n]]>'.format(cdata_text)
 
 class _TestInfo(object):
 
@@ -55,22 +58,26 @@ class _TestInfo(object):
         info._error = error
         return info
 
+    def xml(self):
+        """Create an XML tag with information about this test case.
+
+        """
+        testcase = ET.Element("testcase")
+        testcase.set('classname', self._class)
+        testcase.set('name', self._method)
+        testcase.set('time', '%.4f' % self._time)
+        if self._failure != None:
+            self._print_error(testcase, 'failure', self._failure)
+        if self._error != None:
+            self._print_error(testcase, 'error', self._error)
+        return testcase
+
     def print_report(self, stream):
         """Print information about this test case in XML format to the
         supplied stream.
 
         """
-        stream.write('  <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % \
-            {
-                "class": self._class,
-                "method": self._method,
-                "time": self._time,
-            })
-        if self._failure != None:
-            self._print_error(stream, 'failure', self._failure)
-        if self._error != None:
-            self._print_error(stream, 'error', self._error)
-        stream.write('</testcase>\n')
+        stream.write(ET.tostring(self.xml()))
 
     def print_report_text(self, stream):
         #stream.write('  <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % \
@@ -89,17 +96,16 @@ class _TestInfo(object):
         if self._failure == None and self._error == None:
             stream.write(' ... ok\n')
 
-    def _print_error(self, stream, tagname, error):
-        """Print information from a failure or error to the supplied stream."""
-        text = escape(str(error[1]))
-        stream.write('\n')
-        stream.write('    <%s type="%s">%s\n' \
-            % (tagname, str(error[0].__name__), text))
+    def _print_error(self, testcase, tagname, error):
+        """
+        Append an XML tag with information from a failure or error to the
+        supplied testcase.
+        """
+        tag = ET.SubElement(testcase, tagname)
+        tag.set('type', str(error[0].__name__))
         tb_stream = StringIO()
         traceback.print_tb(error[2], None, tb_stream)
-        stream.write(escape(tb_stream.getvalue()))
-        stream.write('    </%s>\n' % tagname)
-        stream.write('  ')
+        tag.text ='%s\n%s' % (str(error[1]), tb_stream.getvalue())
 
     def _print_error_text(self, stream, tagname, error):
         """Print information from a failure or error to the supplied stream."""
@@ -152,6 +158,31 @@ class _XMLTestResult(unittest.TestResult):
         unittest.TestResult.addFailure(self, test, err)
         self._failure = err
 
+    def filter_nonprintable_text(self, text):
+        invalid_chars = re.compile(ur'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\xFF\u0100-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]')
+        def invalid_char_replacer(m):
+            return "&#x"+('%04X' % ord(m.group(0)))+";"
+        return re.sub(invalid_chars, invalid_char_replacer, str(text))
+
+    def xml(self, time_taken, out, err):
+        """
+        @return XML tag representing the object
+        @rtype: xml.etree.ElementTree.Element
+        """
+        test_suite = ET.Element('testsuite')
+        test_suite.set('errors', str(len(self.errors)))
+        test_suite.set('failures', str(len(self.failures)))
+        test_suite.set('name', self._test_name)
+        test_suite.set('tests', str(self.testsRun))
+        test_suite.set('time', '%.3f' % time_taken)
+        for info in self._tests:
+            test_suite.append(info.xml())
+        system_out = ET.SubElement(test_suite, 'system-out')
+        system_out.text = cdata(self.filter_nonprintable_text(out))
+        system_err = ET.SubElement(test_suite, 'system-err')
+        system_err.text = cdata(self.filter_nonprintable_text(err))
+        return ET.ElementTree(test_suite)
+
     def print_report(self, stream, time_taken, out, err):
         """Prints the XML report to the supplied stream.
         
@@ -159,19 +190,7 @@ class _XMLTestResult(unittest.TestResult):
         output and standard error streams must be passed in.a
 
         """
-        stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % \
-            { "e": len(self.errors), "f": len(self.failures) })
-        stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % \
-            {
-                "n": self._test_name,
-                "t": self.testsRun,
-                "time": time_taken,
-            })
-        for info in self._tests:
-            info.print_report(stream)
-        stream.write('  <system-out><![CDATA[%s]]></system-out>\n' % out)
-        stream.write('  <system-err><![CDATA[%s]]></system-err>\n' % err)
-        stream.write('</testsuite>\n')
+        stream.write(ET.tostring(self.xml(time_taken, out, err).getroot(), encoding='utf-8', method='xml'))
 
     def print_report_text(self, stream, time_taken, out, err):
         """Prints the text report to the supplied stream.
@@ -247,9 +266,6 @@ class XMLTestRunner(object):
         result.print_report(stream, time_taken, out_s, err_s)
 
         result.print_report_text(sys.stdout, time_taken, out_s, err_s)
-        
-        if self._stream == None:
-            stream.close()
 
         return result
 
diff --git a/tools/rosunit/test/dotname_cases.py b/tools/rosunit/test/dotname_cases.py
new file mode 100755
index 0000000..b7cd25e
--- /dev/null
+++ b/tools/rosunit/test/dotname_cases.py
@@ -0,0 +1,36 @@
+import unittest
+
+
+class CaseA(unittest.TestCase):
+
+    def runTest(self):
+        self.assertTrue(True)
+
+
+class CaseB(unittest.TestCase):
+
+    def runTest(self):
+        self.assertTrue(True)
+
+
+class DotnameLoadingSuite(unittest.TestSuite):
+
+    def __init__(self):
+        super(DotnameLoadingSuite, self).__init__()
+        self.addTest(CaseA())
+        self.addTest(CaseB())
+
+
+class DotnameLoadingTest(unittest.TestCase):
+
+    def test_a(self):
+        self.assertTrue(True)
+
+    def test_b(self):
+        self.assertTrue(True)
+
+
+class NotTestCase():
+
+    def not_test(self):
+        pass
diff --git a/tools/rosunit/test/setup.cfg b/tools/rosunit/test/setup.cfg
deleted file mode 100644
index 945109e..0000000
--- a/tools/rosunit/test/setup.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-[nosetests]
-with-coverage=1
-cover-package=rosunit
-with-xunit=1
diff --git a/tools/rosunit/test/test_dotname.py b/tools/rosunit/test/test_dotname.py
new file mode 100755
index 0000000..b254067
--- /dev/null
+++ b/tools/rosunit/test/test_dotname.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+
+# This file should be run using a non-ros unit test framework such as nose using
+# nosetests test_dotname.py. Alternatively, just run with python test_dotname.py.
+# You will get the output from rostest as well.
+
+import unittest
+import rosunit
+from dotname_cases import DotnameLoadingTest, NotTestCase
+
+
+class TestDotnameLoading(unittest.TestCase):
+
+    def test_class_basic(self):
+        rosunit.unitrun('test_rosunit', 'test_class_basic', DotnameLoadingTest)
+
+    def test_class_dotname(self):
+        rosunit.unitrun('test_rosunit', 'test_class_dotname', 'test.dotname_cases.DotnameLoadingTest')
+
+    def test_method_dotname(self):
+        rosunit.unitrun('test_rosunit', 'test_method_dotname', 'test.dotname_cases.DotnameLoadingTest.test_a')
+
+    def test_suite_dotname(self):
+        rosunit.unitrun('test_rosunit', 'test_suite_dotname', 'test.dotname_cases.DotnameLoadingSuite')
+
+    def test_class_basic_nottest(self):
+        # class which exists but is not a TestCase
+        with self.assertRaises(SystemExit):
+            rosunit.unitrun('test_rosunit', 'test_class_basic_nottest', NotTestCase)
+
+    def test_class_dotname_nottest(self):
+        # class which exists but is not a valid test
+        with self.assertRaises(TypeError):
+            rosunit.unitrun('test_rosunit', 'test_class_dotname_nottest', 'test.dotname_cases.NotTestCase')
+
+    def test_class_dotname_noexist(self):
+        # class which does not exist in the module
+        with self.assertRaises(AttributeError):
+            rosunit.unitrun('test_rosunit', 'test_class_dotname_noexist', 'test.dotname_cases.DotnameLoading')
+
+    def test_method_dotname_noexist(self):
+        # method which does not exist in the class
+        with self.assertRaises(AttributeError):
+            rosunit.unitrun('test_rosunit', 'test_method_dotname_noexist', 'test.dotname_cases.DotnameLoadingTest.not_method')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tools/rosunit/test/test_junitxml.py b/tools/rosunit/test/test_junitxml.py
index 64408b5..d6b58b0 100644
--- a/tools/rosunit/test/test_junitxml.py
+++ b/tools/rosunit/test/test_junitxml.py
@@ -91,6 +91,44 @@ def _writeMockResultFile(result):
         if len(result.suites) > 1 or result.noSuitesRoot == False:
             f.write('</testsuites>\n')
 
+class XmlResultTestGeneration(unittest.TestCase):
+    def setUp(self):
+        global junitxml
+        if junitxml is None:
+            import rosunit.junitxml
+            junitxml = rosunit.junitxml
+
+    def tearDown(self):
+        pass
+
+    def testGenerateError(self):
+        error = junitxml.TestError('error_type', 'error_text')
+        error_str = error.xml()
+        self.assertEquals('''<error type="error_type"><![CDATA[
+error_text
+]]></error>''', error_str)
+
+    def testGenerateFailure(self):
+        failure = junitxml.TestFailure('failure_type', 'failure_text')
+        failure_str = failure.xml()
+        self.assertEquals('''<failure type="failure_type"><![CDATA[
+failure_text
+]]></failure>''', failure_str)
+
+    def testGenerateTestCaseResult(self):
+        testcase = junitxml.TestCaseResult('test_case')
+        error = junitxml.TestError('error_type', 'error_text')
+        error_str = error.xml()
+        failure = junitxml.TestFailure('failure_type', 'failure_text')
+        failure_str = failure.xml()
+        testcase.add_error(error)
+        testcase.add_failure(failure)
+        testcase_str = testcase.xml()
+        self.assertEquals('''<testcase classname="" name="test_case" time="0.0"><failure type="failure_type"><![CDATA[
+failure_text
+]]></failure><error type="error_type"><![CDATA[
+error_text
+]]></error></testcase>''', testcase_str)
 
 class XmlResultTestRead(unittest.TestCase):
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ros/ros-ros.git



More information about the debian-science-commits mailing list