diff --git a/test/test_roslib/CMakeLists.txt b/test/test_roslib/CMakeLists.txt
new file mode 100644
index 00000000..d70db84e
--- /dev/null
+++ b/test/test_roslib/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.4.6)
+include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
+rosbuild_init()
+rosbuild_genmsg()
+# unit tests
+rosbuild_add_pyunit(test/test_md5sums.py)
+rosbuild_add_pyunit(test/test_roslib.py)
+rosbuild_add_pyunit(test/test_roslib_exceptions.py)
+rosbuild_add_pyunit(test/test_roslib_genpy.py)
+rosbuild_add_pyunit(test/test_roslib_gentools.py)
+rosbuild_add_pyunit(test/test_roslib_manifest.py)
+rosbuild_add_pyunit(test/test_roslib_manifestlib.py)
+rosbuild_add_pyunit(test/test_roslib_message.py)
+rosbuild_add_pyunit(test/test_roslib_msgs.py)
+rosbuild_add_pyunit(test/test_roslib_os_detect.py)
+rosbuild_add_pyunit(test/test_roslib_names.py)
+rosbuild_add_pyunit(test/test_roslib_network.py)
+rosbuild_add_pyunit(test/test_roslib_packages.py)
+rosbuild_add_pyunit(test/test_roslib_params.py)
+rosbuild_add_pyunit(test/test_roslib_rosenv.py)
+rosbuild_add_pyunit(test/test_roslib_rospack.py)
+rosbuild_add_pyunit(test/test_roslib_rostime.py)
+rosbuild_add_pyunit(test/test_roslib_scriptutil.py)
+rosbuild_add_pyunit(test/test_roslib_stacks.py)
+rosbuild_add_pyunit(test/test_roslib_substitution_args.py)
+rosbuild_add_pyunit(test/test_roslib_xmlrpc.py)
+
+#integration tests
+
+rosbuild_add_boost_directories()
+rosbuild_add_gtest(test/utest test/utest.cpp)
+rosbuild_link_boost(test/utest thread)
+
+
+rosbuild_add_gtest(test_package test/package.cpp)
+target_link_libraries(test_package roslib)
diff --git a/test/test_roslib/Makefile b/test/test_roslib/Makefile
new file mode 100644
index 00000000..bbd3fc60
--- /dev/null
+++ b/test/test_roslib/Makefile
@@ -0,0 +1 @@
+include $(shell rospack find mk)/cmake.mk
diff --git a/test/test_roslib/manifest.xml b/test/test_roslib/manifest.xml
new file mode 100644
index 00000000..1ec7908f
--- /dev/null
+++ b/test/test_roslib/manifest.xml
@@ -0,0 +1,17 @@
+
+
+ Unit tests verifying that roslib is operating as expected.
+
+ Jeremy Leibs/leibs@willowgarage.com, Ken Conley/kwc@willowgarage.com
+ BSD
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/test_roslib/msg/ArrayOfMsgs.msg b/test/test_roslib/msg/ArrayOfMsgs.msg
new file mode 100644
index 00000000..584a3f47
--- /dev/null
+++ b/test/test_roslib/msg/ArrayOfMsgs.msg
@@ -0,0 +1,3 @@
+std_msgs/String[] strings
+std_msgs/Time[] times
+std_msgs/MultiArrayLayout[] muls
\ No newline at end of file
diff --git a/test/test_roslib/msg/FieldNameChange1.msg b/test/test_roslib/msg/FieldNameChange1.msg
new file mode 100644
index 00000000..ce0c137e
--- /dev/null
+++ b/test/test_roslib/msg/FieldNameChange1.msg
@@ -0,0 +1 @@
+SameSubMsg1 a
\ No newline at end of file
diff --git a/test/test_roslib/msg/FieldNameChange2.msg b/test/test_roslib/msg/FieldNameChange2.msg
new file mode 100644
index 00000000..3595c01e
--- /dev/null
+++ b/test/test_roslib/msg/FieldNameChange2.msg
@@ -0,0 +1 @@
+SameSubMsg1 b
\ No newline at end of file
diff --git a/test/test_roslib/msg/FillEmbedTime.msg b/test/test_roslib/msg/FillEmbedTime.msg
new file mode 100644
index 00000000..ffd0b854
--- /dev/null
+++ b/test/test_roslib/msg/FillEmbedTime.msg
@@ -0,0 +1,5 @@
+time t
+duration d
+std_msgs/String str_msg
+std_msgs/String[] str_msg_array
+int32 i32
\ No newline at end of file
diff --git a/test/test_roslib/msg/FillSimple.msg b/test/test_roslib/msg/FillSimple.msg
new file mode 100644
index 00000000..164965e2
--- /dev/null
+++ b/test/test_roslib/msg/FillSimple.msg
@@ -0,0 +1,4 @@
+int32 i32
+string str
+int32[] i32_array
+bool b
\ No newline at end of file
diff --git a/test/test_roslib/msg/HeaderTest.msg b/test/test_roslib/msg/HeaderTest.msg
new file mode 100644
index 00000000..d236dda1
--- /dev/null
+++ b/test/test_roslib/msg/HeaderTest.msg
@@ -0,0 +1,2 @@
+Header header
+int32 i32
\ No newline at end of file
diff --git a/test/test_roslib/msg/SameSubMsg1.msg b/test/test_roslib/msg/SameSubMsg1.msg
new file mode 100644
index 00000000..bbc7ede3
--- /dev/null
+++ b/test/test_roslib/msg/SameSubMsg1.msg
@@ -0,0 +1,5 @@
+int32 a
+float32 b
+string c
+uint64[10] d
+float64[] e
\ No newline at end of file
diff --git a/test/test_roslib/msg/SameSubMsg2.msg b/test/test_roslib/msg/SameSubMsg2.msg
new file mode 100644
index 00000000..bbc7ede3
--- /dev/null
+++ b/test/test_roslib/msg/SameSubMsg2.msg
@@ -0,0 +1,5 @@
+int32 a
+float32 b
+string c
+uint64[10] d
+float64[] e
\ No newline at end of file
diff --git a/test/test_roslib/msg/SameSubMsg3.msg b/test/test_roslib/msg/SameSubMsg3.msg
new file mode 100644
index 00000000..2927bb14
--- /dev/null
+++ b/test/test_roslib/msg/SameSubMsg3.msg
@@ -0,0 +1,11 @@
+
+# Lots of comments
+int32 a #And more comments
+float32 b
+string c
+# And also some white space
+
+
+uint64[10] d
+ float64[] e
+
diff --git a/test/test_roslib/msg/TypeNameChange1.msg b/test/test_roslib/msg/TypeNameChange1.msg
new file mode 100644
index 00000000..ce0c137e
--- /dev/null
+++ b/test/test_roslib/msg/TypeNameChange1.msg
@@ -0,0 +1 @@
+SameSubMsg1 a
\ No newline at end of file
diff --git a/test/test_roslib/msg/TypeNameChange2.msg b/test/test_roslib/msg/TypeNameChange2.msg
new file mode 100644
index 00000000..3fb21aa1
--- /dev/null
+++ b/test/test_roslib/msg/TypeNameChange2.msg
@@ -0,0 +1 @@
+SameSubMsg2 a
\ No newline at end of file
diff --git a/test/test_roslib/msg/TypeNameChangeArray1.msg b/test/test_roslib/msg/TypeNameChangeArray1.msg
new file mode 100644
index 00000000..828983dc
--- /dev/null
+++ b/test/test_roslib/msg/TypeNameChangeArray1.msg
@@ -0,0 +1 @@
+SameSubMsg1[] a
\ No newline at end of file
diff --git a/test/test_roslib/msg/TypeNameChangeArray2.msg b/test/test_roslib/msg/TypeNameChangeArray2.msg
new file mode 100644
index 00000000..90200b02
--- /dev/null
+++ b/test/test_roslib/msg/TypeNameChangeArray2.msg
@@ -0,0 +1 @@
+SameSubMsg2[] a
\ No newline at end of file
diff --git a/test/test_roslib/msg/TypeNameChangeComplex1.msg b/test/test_roslib/msg/TypeNameChangeComplex1.msg
new file mode 100644
index 00000000..febf0c5f
--- /dev/null
+++ b/test/test_roslib/msg/TypeNameChangeComplex1.msg
@@ -0,0 +1,2 @@
+SameSubMsg1[] a
+SameSubMsg2[10] b
diff --git a/test/test_roslib/msg/TypeNameChangeComplex2.msg b/test/test_roslib/msg/TypeNameChangeComplex2.msg
new file mode 100644
index 00000000..8280896f
--- /dev/null
+++ b/test/test_roslib/msg/TypeNameChangeComplex2.msg
@@ -0,0 +1,2 @@
+SameSubMsg2[] a
+SameSubMsg3[10] b
diff --git a/test/test_roslib/test/distro/boxturtle.rosdistro b/test/test_roslib/test/distro/boxturtle.rosdistro
new file mode 100644
index 00000000..5ae49e48
--- /dev/null
+++ b/test/test_roslib/test/distro/boxturtle.rosdistro
@@ -0,0 +1,177 @@
+_rules:
+ rp-nobranch: &id002 {dev-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/trunk',
+ distro-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+ wg-nobranch: &id001 {dev-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/trunk',
+ distro-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+ wg-ros-pkg: &id003 {dev-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/branches/$STACK_NAME-1.0',
+ distro-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+release: boxturtle
+stacks:
+ _rules: {dev-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/branches/$STACK_NAME-1.0',
+ distro-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+ arm_navigation:
+ _rules: *id001
+ version: 0.2.2
+ camera_drivers:
+ _rules: *id002
+ version: 0.9.2
+ collision_environment:
+ _rules: *id001
+ version: 0.2.0
+ common: {version: 1.0.3}
+ common_msgs: {version: 1.0.0}
+ diagnostics: {version: 1.0.2}
+ driver_common: {version: 1.0.1}
+ executive_python:
+ _rules: *id001
+ version: 0.1.0
+ geometry: {version: 1.0.2}
+ image_common: {version: 1.0.1}
+ image_pipeline: {version: 1.0.0}
+ image_transport_plugins:
+ _rules: *id002
+ version: 0.1.1
+ imu_drivers: {version: 1.0.1}
+ joystick_drivers: {version: 1.0.1}
+ kinematics:
+ _rules: *id001
+ version: 0.1.0
+ laser_drivers: {version: 1.0.4}
+ laser_pipeline: {version: 1.0.1}
+ motion_planners:
+ _rules: *id001
+ version: 0.2.0
+ motion_planning_common:
+ _rules: *id001
+ version: 0.2.1
+ motion_planning_environment:
+ _rules: *id001
+ version: 0.2.0
+ motion_planning_visualization:
+ _rules: *id001
+ version: 0.2.0
+ navigation: {version: 1.0.4}
+ physics_ode: {version: 1.0.4}
+ pr2_apps:
+ _rules: *id001
+ version: 0.2.1
+ pr2_arm_navigation:
+ _rules: *id001
+ version: 0.2.1
+ pr2_arm_navigation_apps:
+ _rules: *id001
+ version: 0.2.0
+ pr2_arm_navigation_tests:
+ _rules: *id001
+ version: 0.2.0
+ pr2_calibration:
+ _rules: *id001
+ version: 0.1.2
+ pr2_common:
+ _rules: *id003
+ version: 1.0.2
+ pr2_common_actions:
+ _rules: *id001
+ version: 0.1.3
+ pr2_controllers:
+ _rules: *id003
+ version: 1.0.0
+ pr2_doors:
+ _rules: *id001
+ version: 0.2.9
+ pr2_ethercat_drivers:
+ _rules: *id001
+ version: 1.0.3
+ pr2_gui:
+ _rules: *id003
+ version: 1.0.0
+ pr2_kinematics:
+ _rules: *id001
+ version: 0.2.0
+ pr2_kinematics_with_constraints:
+ _rules: *id001
+ version: 0.2.0
+ pr2_mechanism:
+ _rules: *id003
+ version: 1.0.2
+ pr2_navigation:
+ _rules: *id001
+ version: 0.1.1
+ pr2_navigation_apps:
+ _rules: *id001
+ version: 0.1.1
+ pr2_plugs:
+ _rules: *id001
+ version: 0.2.3
+ pr2_power_drivers:
+ _rules: *id001
+ version: 1.0.2
+ pr2_robot:
+ _rules: *id001
+ version: 0.3.7
+ pr2_simulator:
+ _rules: *id003
+ version: 1.0.3
+ pr2_web_apps:
+ _rules: *id001
+ version: 0.3.4
+ robot_calibration:
+ _rules: *id002
+ version: 0.2.0
+ robot_model: {version: 1.0.1}
+ ros:
+ _rules: {dev-svn: 'https://code.ros.org/svn/ros/stacks/ros/tags/rc', distro-svn: 'https://code.ros.org/svn/ros/stacks/ros/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/ros/stacks/ros/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+ version: 1.0.1
+ ros_experimental:
+ _rules: {dev-svn: 'https://code.ros.org/svn/ros/stacks/$STACK_NAME/trunk', distro-svn: 'https://code.ros.org/svn/ros/stacks/$STACK_NAME/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/ros/stacks/ros/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+ version: 0.1.0
+ simulator_gazebo: {version: 1.0.3}
+ simulator_stage: {version: 1.0.0}
+ slam_gmapping: {version: 1.0.0}
+ sound_drivers: {version: 1.0.3}
+ test_rule_override:
+ _rules:
+ dev-svn: 'https://madeup/stuff/$STACK_NAME/trunk'
+ version: 0.1.3
+ trajectory_filters:
+ _rules: *id001
+ version: 0.2.2
+ vision_opencv: {version: 1.0.1}
+ visualization: {version: 1.0.1}
+ visualization_common: {version: 1.0.1}
+ web_interface:
+ _rules: *id001
+ version: 0.3.15
+ wg_common:
+ _rules: *id001
+ version: 0.1.2
+ wg_pr2_apps:
+ _rules: *id001
+ version: 0.1.1
+ wifi_drivers:
+ _rules: *id001
+ version: 0.1.3
+variants:
+- base:
+ stacks: [ros, camera_drivers, common_msgs, common, diagnostics, driver_common,
+ geometry, image_common, image_pipeline, imu_drivers, joystick_drivers, laser_drivers,
+ laser_pipeline, navigation, physics_ode, robot_model, simulator_gazebo, simulator_stage,
+ slam_gmapping, sound_drivers, vision_opencv, visualization_common, visualization]
+- pr2:
+ extends: base
+ stacks: [image_transport_plugins, pr2_apps, pr2_common, pr2_controllers, pr2_ethercat_drivers,
+ pr2_gui, pr2_mechanism, pr2_power_drivers, pr2_robot, pr2_simulator, web_interface,
+ wifi_drivers]
+version: 6
diff --git a/test/test_roslib/test/distro/latest.rosdistro b/test/test_roslib/test/distro/latest.rosdistro
new file mode 100644
index 00000000..939af689
--- /dev/null
+++ b/test/test_roslib/test/distro/latest.rosdistro
@@ -0,0 +1,171 @@
+_rules:
+ wg-ros-pkg: &id001 {dev-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/trunk',
+ distro-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+release: latest
+stacks:
+ _rules: {dev-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/trunk', distro-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+ arm_navigation:
+ _rules: *id001
+ version: 0.2.2
+ camera_drivers: {version: 0.9.2}
+ collision_environment:
+ _rules: *id001
+ version: 0.2.0
+ common: {version: 1.1.0}
+ common_msgs: {version: 1.1.1}
+ diagnostics: {version: 1.0.2}
+ driver_common: {version: 1.0.1}
+ executive_python:
+ _rules: *id001
+ version: 0.1.0
+ geometry: {version: 1.0.2}
+ image_common: {version: 1.0.1}
+ image_pipeline: {version: 1.1.1}
+ image_transport_plugins: {version: 0.1.1}
+ imu_drivers: {version: 1.0.1}
+ joystick_drivers: {version: 1.0.1}
+ kinematics:
+ _rules: *id001
+ version: 0.2.0
+ laser_drivers: {version: 1.0.4}
+ laser_pipeline: {version: 1.0.1}
+ motion_planners:
+ _rules: *id001
+ version: 0.2.0
+ motion_planning_common:
+ _rules: *id001
+ version: 0.2.1
+ motion_planning_environment:
+ _rules: {dev-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/trunk',
+ distro-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/wg-ros-pkg/stacks/$STACK_NAME/tags/$STACK_NAME-$STACK_VERSION',
+ source-tarball: 'http://ros.org/download/stacks/$STACK_NAME/$STACK_NAME-$STACK_VERSION.tar.bz2'}
+ version: 0.2.0
+ motion_planning_visualization:
+ _rules: *id001
+ version: 0.2.0
+ navigation: {version: 1.0.4}
+ navigation_experimental: {version: 0.1.0}
+ physics_ode: {version: 1.0.4}
+ point_cloud_perception: {version: 0.1.0}
+ pr2_apps:
+ _rules: *id001
+ version: 0.2.1
+ pr2_arm_navigation:
+ _rules: *id001
+ version: 0.2.1
+ pr2_arm_navigation_apps:
+ _rules: *id001
+ version: 0.2.0
+ pr2_arm_navigation_tests:
+ _rules: *id001
+ version: 0.2.0
+ pr2_calibration:
+ _rules: *id001
+ version: 0.3.0
+ pr2_common:
+ _rules: *id001
+ version: 1.0.2
+ pr2_common_actions:
+ _rules: *id001
+ version: 0.1.3
+ pr2_controllers:
+ _rules: *id001
+ version: 1.0.1
+ pr2_doors:
+ _rules: *id001
+ version: 0.2.9
+ pr2_ethercat_drivers:
+ _rules: *id001
+ version: 1.0.3
+ pr2_gui:
+ _rules: *id001
+ version: 1.0.0
+ pr2_kinematics:
+ _rules: *id001
+ version: 0.2.0
+ pr2_kinematics_with_constraints:
+ _rules: *id001
+ version: 0.2.0
+ pr2_mechanism:
+ _rules: *id001
+ version: 1.0.1
+ pr2_navigation:
+ _rules: *id001
+ version: 0.1.1
+ pr2_navigation_apps:
+ _rules: *id001
+ version: 0.1.1
+ pr2_plugs:
+ _rules: *id001
+ version: 0.2.4
+ pr2_power_drivers:
+ _rules: *id001
+ version: 1.0.2
+ pr2_robot:
+ _rules: *id001
+ version: 0.3.7
+ pr2_simulator:
+ _rules: *id001
+ version: 1.0.3
+ pr2_web_apps:
+ _rules: *id001
+ version: 0.3.5
+ robot_calibration: {version: 0.2.1}
+ robot_model: {version: 1.0.1}
+ ros:
+ _rules: {dev-svn: 'https://code.ros.org/svn/ros/stacks/ros/tags/rc', distro-svn: 'https://code.ros.org/svn/ros/stacks/ros/tags/$RELEASE_NAME',
+ release-svn: 'https://code.ros.org/svn/ros/stacks/ros/tags/$STACK_NAME-$STACK_VERSION'}
+ version: 1.1.1
+ simulator_gazebo: {version: 1.1.1}
+ simulator_stage: {version: 1.0.0}
+ slam_gmapping: {version: 1.1.0}
+ sound_drivers: {version: 1.0.3}
+ texas_drivers:
+ _rules: *id001
+ version: 0.2.10
+ trajectory_filters:
+ _rules: *id001
+ version: 0.2.2
+ vision_opencv: {version: 1.1.0}
+ visualization:
+ _rules: {dev-svn: 'https://code.ros.org/svn/ros-pkg/stacks/$STACK_NAME/branches/visualization-1.0'}
+ version: 1.0.2
+ visualization_common: {version: 1.0.1}
+ web_interface:
+ _rules: *id001
+ version: 0.3.16
+ wg_common:
+ _rules: *id001
+ version: 0.1.2
+ wg_pr2_apps:
+ _rules: *id001
+ version: 0.1.1
+ wifi_drivers:
+ _rules: *id001
+ version: 0.1.3
+variants:
+- base:
+ stacks: [ros, camera_drivers, common_msgs, common, diagnostics, driver_common,
+ geometry, image_common, image_transport_plugins, image_pipeline, imu_drivers,
+ joystick_drivers, laser_drivers, laser_pipeline, navigation, physics_ode, robot_model,
+ point_cloud_perception, simulator_gazebo, simulator_stage, slam_gmapping, sound_drivers,
+ vision_opencv, visualization_common, visualization]
+- pr2:
+ extends: base
+ stacks: [pr2_common, pr2_controllers, pr2_ethercat_drivers, pr2_gui,
+ pr2_mechanism, pr2_power_drivers, pr2_robot, pr2_simulator]
+- pr2all:
+ extends: pr2
+ stacks: [arm_navigation, collision_environment, kinematics, motion_planners, motion_planning_common,
+ motion_planning_environment, motion_planning_visualization, pr2_apps, pr2_arm_navigation,
+ pr2_arm_navigation_apps, pr2_arm_navigation_tests, pr2_calibration,
+ pr2_common_actions, pr2_doors, pr2_kinematics, pr2_kinematics_with_constraints, pr2_navigation,
+ pr2_navigation_apps, pr2_plugs,
+ pr2_web_apps, robot_calibration, trajectory_filters, web_interface, wg_common,
+ wg_pr2_apps, wifi_drivers]
+version: '$Revision: 468 $'
diff --git a/test/test_roslib/test/fake_node.py b/test/test_roslib/test/fake_node.py
new file mode 100755
index 00000000..0e302153
--- /dev/null
+++ b/test/test_roslib/test/fake_node.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+# this node only exists to test find_node functionality
+
+print "hello"
diff --git a/test/test_roslib/test/manifest_tests/bad1.xml b/test/test_roslib/test/manifest_tests/bad1.xml
new file mode 100644
index 00000000..7dd21ebf
--- /dev/null
+++ b/test/test_roslib/test/manifest_tests/bad1.xml
@@ -0,0 +1 @@
+not xml
diff --git a/test/test_roslib/test/manifest_tests/bad2.xml b/test/test_roslib/test/manifest_tests/bad2.xml
new file mode 100644
index 00000000..9a8acc8c
--- /dev/null
+++ b/test/test_roslib/test/manifest_tests/bad2.xml
@@ -0,0 +1,20 @@
+
+ Line 1
+Line 2
+
+ The authors
+go here
+ Public Domain
+with other stuff
+ http://pr.willowgarage.com/package/
+ http://www.willowgarage.com/files/willowgarage/robot10.jpg
+
+
+
+
+
+
+
+
+
+
diff --git a/test/test_roslib/test/manifest_tests/bad3.xml b/test/test_roslib/test/manifest_tests/bad3.xml
new file mode 100644
index 00000000..40f6ae9c
--- /dev/null
+++ b/test/test_roslib/test/manifest_tests/bad3.xml
@@ -0,0 +1,11 @@
+
+ Line 1
+
+ Second description
+
+
+ The authors
+go here
+ Public Domain
+with other stuff
+
diff --git a/test/test_roslib/test/manifest_tests/example1.xml b/test/test_roslib/test/manifest_tests/example1.xml
new file mode 100644
index 00000000..9a2d1321
--- /dev/null
+++ b/test/test_roslib/test/manifest_tests/example1.xml
@@ -0,0 +1,20 @@
+
+ Line 1
+Line 2
+
+ The authors
+go here
+ Public Domain
+with other stuff
+ http://pr.willowgarage.com/package/
+ http://www.willowgarage.com/files/willowgarage/robot10.jpg
+
+
+
+
+
+
+
+
+
+
diff --git a/test/test_roslib/test/manifest_tests/stack_example1.xml b/test/test_roslib/test/manifest_tests/stack_example1.xml
new file mode 100644
index 00000000..e83156e7
--- /dev/null
+++ b/test/test_roslib/test/manifest_tests/stack_example1.xml
@@ -0,0 +1,13 @@
+
+ Line 1
+Line 2
+
+ The authors
+go here
+ Public Domain
+with other stuff
+ http://ros.org/stack/
+ http://www.willowgarage.com/files/willowgarage/robot10.jpg
+
+
+
diff --git a/test/test_roslib/test/md5tests/different/constants1.txt b/test/test_roslib/test/md5tests/different/constants1.txt
new file mode 100644
index 00000000..bbdcc07b
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/constants1.txt
@@ -0,0 +1 @@
+int32 x=1
diff --git a/test/test_roslib/test/md5tests/different/constants2.txt b/test/test_roslib/test/md5tests/different/constants2.txt
new file mode 100644
index 00000000..163e4308
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/constants2.txt
@@ -0,0 +1 @@
+int32 x=2
diff --git a/test/test_roslib/test/md5tests/different/constants3.txt b/test/test_roslib/test/md5tests/different/constants3.txt
new file mode 100644
index 00000000..33c5b1db
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/constants3.txt
@@ -0,0 +1 @@
+int32 x=10
diff --git a/test/test_roslib/test/md5tests/different/constantsB1.txt b/test/test_roslib/test/md5tests/different/constantsB1.txt
new file mode 100644
index 00000000..3839b46f
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/constantsB1.txt
@@ -0,0 +1,3 @@
+# protect against aliasing
+string s=u
+int32 a
diff --git a/test/test_roslib/test/md5tests/different/constantsB2.txt b/test/test_roslib/test/md5tests/different/constantsB2.txt
new file mode 100644
index 00000000..2901a264
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/constantsB2.txt
@@ -0,0 +1,2 @@
+# protect against aliasing
+string s=uint32 a
diff --git a/test/test_roslib/test/md5tests/different/fields1.txt b/test/test_roslib/test/md5tests/different/fields1.txt
new file mode 100644
index 00000000..c763ffa5
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/fields1.txt
@@ -0,0 +1,3 @@
+int32 a
+int32 b
+int32 c
diff --git a/test/test_roslib/test/md5tests/different/fields2.txt b/test/test_roslib/test/md5tests/different/fields2.txt
new file mode 100644
index 00000000..035777c3
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/fields2.txt
@@ -0,0 +1,2 @@
+int32 a
+int32 b
diff --git a/test/test_roslib/test/md5tests/different/fields3.txt b/test/test_roslib/test/md5tests/different/fields3.txt
new file mode 100644
index 00000000..aabefcb1
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/fields3.txt
@@ -0,0 +1,4 @@
+int32 a
+int32 b
+int32 c
+int32 d
diff --git a/test/test_roslib/test/md5tests/different/fields4.txt b/test/test_roslib/test/md5tests/different/fields4.txt
new file mode 100644
index 00000000..518e2d21
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/fields4.txt
@@ -0,0 +1,3 @@
+int32 a1
+int32 b
+int32 c
diff --git a/test/test_roslib/test/md5tests/different/fields5.txt b/test/test_roslib/test/md5tests/different/fields5.txt
new file mode 100644
index 00000000..9a0abc3d
--- /dev/null
+++ b/test/test_roslib/test/md5tests/different/fields5.txt
@@ -0,0 +1,3 @@
+uint32 a
+int32 b
+int32 c
diff --git a/test/test_roslib/test/md5tests/md5text/constant1.txt b/test/test_roslib/test/md5tests/md5text/constant1.txt
new file mode 100644
index 00000000..8e09574b
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/constant1.txt
@@ -0,0 +1 @@
+int32 x=123456
diff --git a/test/test_roslib/test/md5tests/md5text/constant2.txt b/test/test_roslib/test/md5tests/md5text/constant2.txt
new file mode 100644
index 00000000..fefbb572
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/constant2.txt
@@ -0,0 +1 @@
+int32 x = 123456
diff --git a/test/test_roslib/test/md5tests/md5text/constant3.txt b/test/test_roslib/test/md5tests/md5text/constant3.txt
new file mode 100644
index 00000000..ac5f6f97
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/constant3.txt
@@ -0,0 +1,3 @@
+#x is a value
+int32 x=123456 #a constant
+#i'm done
diff --git a/test/test_roslib/test/md5tests/md5text/constantB1.txt b/test/test_roslib/test/md5tests/md5text/constantB1.txt
new file mode 100644
index 00000000..2db0afd6
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/constantB1.txt
@@ -0,0 +1 @@
+string foo="#bar
diff --git a/test/test_roslib/test/md5tests/md5text/constantB2.txt b/test/test_roslib/test/md5tests/md5text/constantB2.txt
new file mode 100644
index 00000000..a6bd453d
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/constantB2.txt
@@ -0,0 +1,3 @@
+#blah
+string foo ="#bar
+#b
diff --git a/test/test_roslib/test/md5tests/md5text/constantC1.txt b/test/test_roslib/test/md5tests/md5text/constantC1.txt
new file mode 100644
index 00000000..f0b3d0a2
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/constantC1.txt
@@ -0,0 +1,6 @@
+int32 x=123
+int32 y=234
+int32 z=345
+float32 a=1.0
+float32 b=2.0
+float32 pi=3.14159
diff --git a/test/test_roslib/test/md5tests/md5text/constantC2.txt b/test/test_roslib/test/md5tests/md5text/constantC2.txt
new file mode 100644
index 00000000..ac0753b7
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/constantC2.txt
@@ -0,0 +1,6 @@
+int32 x = 123
+int32 y = 234
+int32 z = 345
+float32 a= 1.0
+float32 b= 2.0
+float32 pi = 3.14159
diff --git a/test/test_roslib/test/md5tests/md5text/embed1.txt b/test/test_roslib/test/md5tests/md5text/embed1.txt
new file mode 100644
index 00000000..4eda8959
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/embed1.txt
@@ -0,0 +1 @@
+acffd30cd6b6de30f120938c17c593fb log
diff --git a/test/test_roslib/test/md5tests/md5text/embed2.txt b/test/test_roslib/test/md5tests/md5text/embed2.txt
new file mode 100644
index 00000000..c0bde1cf
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/embed2.txt
@@ -0,0 +1 @@
+roslib/Log log
diff --git a/test/test_roslib/test/md5tests/md5text/embed3.txt b/test/test_roslib/test/md5tests/md5text/embed3.txt
new file mode 100644
index 00000000..56c09dd3
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/embed3.txt
@@ -0,0 +1,3 @@
+#commented
+roslib/Log log
+#another comment
diff --git a/test/test_roslib/test/md5tests/md5text/embed4.txt b/test/test_roslib/test/md5tests/md5text/embed4.txt
new file mode 100644
index 00000000..a9d30dd7
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/embed4.txt
@@ -0,0 +1,4 @@
+#comment. note the stripped package name
+Log log
+
+#comment
diff --git a/test/test_roslib/test/md5tests/md5text/empty1.txt b/test/test_roslib/test/md5tests/md5text/empty1.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_roslib/test/md5tests/md5text/empty2.txt b/test/test_roslib/test/md5tests/md5text/empty2.txt
new file mode 100644
index 00000000..8d1c8b69
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/empty2.txt
@@ -0,0 +1 @@
+
diff --git a/test/test_roslib/test/md5tests/md5text/empty3.txt b/test/test_roslib/test/md5tests/md5text/empty3.txt
new file mode 100644
index 00000000..32481188
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/empty3.txt
@@ -0,0 +1 @@
+### Just a comment
diff --git a/test/test_roslib/test/md5tests/md5text/empty4.txt b/test/test_roslib/test/md5tests/md5text/empty4.txt
new file mode 100644
index 00000000..1b9cb525
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/empty4.txt
@@ -0,0 +1,6 @@
+# A comment
+
+# With multiple lines
+
+
+
diff --git a/test/test_roslib/test/md5tests/md5text/field1.txt b/test/test_roslib/test/md5tests/md5text/field1.txt
new file mode 100644
index 00000000..b0369cb9
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/field1.txt
@@ -0,0 +1 @@
+int32 field
diff --git a/test/test_roslib/test/md5tests/md5text/field2.txt b/test/test_roslib/test/md5tests/md5text/field2.txt
new file mode 100644
index 00000000..6699ede2
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/field2.txt
@@ -0,0 +1,2 @@
+#comment before
+int32 field
diff --git a/test/test_roslib/test/md5tests/md5text/field3.txt b/test/test_roslib/test/md5tests/md5text/field3.txt
new file mode 100644
index 00000000..cc58824b
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/field3.txt
@@ -0,0 +1,2 @@
+int32 field
+#comment after
diff --git a/test/test_roslib/test/md5tests/md5text/field4.txt b/test/test_roslib/test/md5tests/md5text/field4.txt
new file mode 100644
index 00000000..40a5023e
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/field4.txt
@@ -0,0 +1 @@
+ int32 field
diff --git a/test/test_roslib/test/md5tests/md5text/field5.txt b/test/test_roslib/test/md5tests/md5text/field5.txt
new file mode 100644
index 00000000..d30c030c
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/field5.txt
@@ -0,0 +1,5 @@
+int32 field #field does something
+
+
+
+#the end
diff --git a/test/test_roslib/test/md5tests/md5text/multi1.txt b/test/test_roslib/test/md5tests/md5text/multi1.txt
new file mode 100644
index 00000000..409be8d5
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/multi1.txt
@@ -0,0 +1,7 @@
+int32 a
+acffd30cd6b6de30f120938c17c593fb log
+string s
+a9c97c1d230cfc112e270351a944ee47 time
+int32 b
+duration d
+time t
diff --git a/test/test_roslib/test/md5tests/md5text/multi2.txt b/test/test_roslib/test/md5tests/md5text/multi2.txt
new file mode 100644
index 00000000..47104aeb
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/multi2.txt
@@ -0,0 +1,14 @@
+# comment about a
+int32 a
+# comment about log
+roslib/Log log
+# comment about s
+string s
+# comment about time
+roslib/Clock time
+# comment about b
+int32 b
+# comment about d
+duration d
+# comment about t
+time t
diff --git a/test/test_roslib/test/md5tests/md5text/multi3.txt b/test/test_roslib/test/md5tests/md5text/multi3.txt
new file mode 100644
index 00000000..19e8a780
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/multi3.txt
@@ -0,0 +1,7 @@
+int32 a
+Log log
+string s
+Clock time
+int32 b
+duration d
+time t
diff --git a/test/test_roslib/test/md5tests/md5text/multi4.txt b/test/test_roslib/test/md5tests/md5text/multi4.txt
new file mode 100644
index 00000000..30e80646
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/multi4.txt
@@ -0,0 +1,16 @@
+# short comment about a
+int32 a #a
+# short comment about log
+Log log #log
+#
+# short comment about s
+string s #s
+# short comment about time
+Clock time #time
+# short comment about b
+int32 b #b
+# short comment about d
+duration d #d
+# short comment about t
+time t # t
+
diff --git a/test/test_roslib/test/md5tests/md5text/multi5.txt b/test/test_roslib/test/md5tests/md5text/multi5.txt
new file mode 100644
index 00000000..402087fc
--- /dev/null
+++ b/test/test_roslib/test/md5tests/md5text/multi5.txt
@@ -0,0 +1,8 @@
+int32 a
+roslib/Log log
+
+string s
+roslib/Clock time
+int32 b
+duration d
+ time t
diff --git a/test/test_roslib/test/md5tests/same/constant1.txt b/test/test_roslib/test/md5tests/same/constant1.txt
new file mode 100644
index 00000000..8e09574b
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/constant1.txt
@@ -0,0 +1 @@
+int32 x=123456
diff --git a/test/test_roslib/test/md5tests/same/constant2.txt b/test/test_roslib/test/md5tests/same/constant2.txt
new file mode 100644
index 00000000..fefbb572
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/constant2.txt
@@ -0,0 +1 @@
+int32 x = 123456
diff --git a/test/test_roslib/test/md5tests/same/constant3.txt b/test/test_roslib/test/md5tests/same/constant3.txt
new file mode 100644
index 00000000..ac5f6f97
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/constant3.txt
@@ -0,0 +1,3 @@
+#x is a value
+int32 x=123456 #a constant
+#i'm done
diff --git a/test/test_roslib/test/md5tests/same/constantB1.txt b/test/test_roslib/test/md5tests/same/constantB1.txt
new file mode 100644
index 00000000..2db0afd6
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/constantB1.txt
@@ -0,0 +1 @@
+string foo="#bar
diff --git a/test/test_roslib/test/md5tests/same/constantB2.txt b/test/test_roslib/test/md5tests/same/constantB2.txt
new file mode 100644
index 00000000..a6bd453d
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/constantB2.txt
@@ -0,0 +1,3 @@
+#blah
+string foo ="#bar
+#b
diff --git a/test/test_roslib/test/md5tests/same/constantC1.txt b/test/test_roslib/test/md5tests/same/constantC1.txt
new file mode 100644
index 00000000..f0b3d0a2
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/constantC1.txt
@@ -0,0 +1,6 @@
+int32 x=123
+int32 y=234
+int32 z=345
+float32 a=1.0
+float32 b=2.0
+float32 pi=3.14159
diff --git a/test/test_roslib/test/md5tests/same/constantC2.txt b/test/test_roslib/test/md5tests/same/constantC2.txt
new file mode 100644
index 00000000..ac0753b7
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/constantC2.txt
@@ -0,0 +1,6 @@
+int32 x = 123
+int32 y = 234
+int32 z = 345
+float32 a= 1.0
+float32 b= 2.0
+float32 pi = 3.14159
diff --git a/test/test_roslib/test/md5tests/same/embed1.txt b/test/test_roslib/test/md5tests/same/embed1.txt
new file mode 100644
index 00000000..c0bde1cf
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/embed1.txt
@@ -0,0 +1 @@
+roslib/Log log
diff --git a/test/test_roslib/test/md5tests/same/embed2.txt b/test/test_roslib/test/md5tests/same/embed2.txt
new file mode 100644
index 00000000..c9ddc1e1
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/embed2.txt
@@ -0,0 +1 @@
+Log log
diff --git a/test/test_roslib/test/md5tests/same/embed3.txt b/test/test_roslib/test/md5tests/same/embed3.txt
new file mode 100644
index 00000000..56c09dd3
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/embed3.txt
@@ -0,0 +1,3 @@
+#commented
+roslib/Log log
+#another comment
diff --git a/test/test_roslib/test/md5tests/same/embed4.txt b/test/test_roslib/test/md5tests/same/embed4.txt
new file mode 100644
index 00000000..a9d30dd7
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/embed4.txt
@@ -0,0 +1,4 @@
+#comment. note the stripped package name
+Log log
+
+#comment
diff --git a/test/test_roslib/test/md5tests/same/empty1.txt b/test/test_roslib/test/md5tests/same/empty1.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_roslib/test/md5tests/same/empty2.txt b/test/test_roslib/test/md5tests/same/empty2.txt
new file mode 100644
index 00000000..8d1c8b69
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/empty2.txt
@@ -0,0 +1 @@
+
diff --git a/test/test_roslib/test/md5tests/same/empty3.txt b/test/test_roslib/test/md5tests/same/empty3.txt
new file mode 100644
index 00000000..32481188
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/empty3.txt
@@ -0,0 +1 @@
+### Just a comment
diff --git a/test/test_roslib/test/md5tests/same/empty4.txt b/test/test_roslib/test/md5tests/same/empty4.txt
new file mode 100644
index 00000000..1b9cb525
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/empty4.txt
@@ -0,0 +1,6 @@
+# A comment
+
+# With multiple lines
+
+
+
diff --git a/test/test_roslib/test/md5tests/same/field1.txt b/test/test_roslib/test/md5tests/same/field1.txt
new file mode 100644
index 00000000..b0369cb9
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/field1.txt
@@ -0,0 +1 @@
+int32 field
diff --git a/test/test_roslib/test/md5tests/same/field2.txt b/test/test_roslib/test/md5tests/same/field2.txt
new file mode 100644
index 00000000..6699ede2
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/field2.txt
@@ -0,0 +1,2 @@
+#comment before
+int32 field
diff --git a/test/test_roslib/test/md5tests/same/field3.txt b/test/test_roslib/test/md5tests/same/field3.txt
new file mode 100644
index 00000000..cc58824b
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/field3.txt
@@ -0,0 +1,2 @@
+int32 field
+#comment after
diff --git a/test/test_roslib/test/md5tests/same/field4.txt b/test/test_roslib/test/md5tests/same/field4.txt
new file mode 100644
index 00000000..40a5023e
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/field4.txt
@@ -0,0 +1 @@
+ int32 field
diff --git a/test/test_roslib/test/md5tests/same/field5.txt b/test/test_roslib/test/md5tests/same/field5.txt
new file mode 100644
index 00000000..d30c030c
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/field5.txt
@@ -0,0 +1,5 @@
+int32 field #field does something
+
+
+
+#the end
diff --git a/test/test_roslib/test/md5tests/same/multi1.txt b/test/test_roslib/test/md5tests/same/multi1.txt
new file mode 100644
index 00000000..e3a63e07
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/multi1.txt
@@ -0,0 +1,7 @@
+int32 a
+roslib/Log log
+string s
+roslib/Clock time
+int32 b
+duration d
+time t
diff --git a/test/test_roslib/test/md5tests/same/multi2.txt b/test/test_roslib/test/md5tests/same/multi2.txt
new file mode 100644
index 00000000..47104aeb
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/multi2.txt
@@ -0,0 +1,14 @@
+# comment about a
+int32 a
+# comment about log
+roslib/Log log
+# comment about s
+string s
+# comment about time
+roslib/Clock time
+# comment about b
+int32 b
+# comment about d
+duration d
+# comment about t
+time t
diff --git a/test/test_roslib/test/md5tests/same/multi3.txt b/test/test_roslib/test/md5tests/same/multi3.txt
new file mode 100644
index 00000000..19e8a780
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/multi3.txt
@@ -0,0 +1,7 @@
+int32 a
+Log log
+string s
+Clock time
+int32 b
+duration d
+time t
diff --git a/test/test_roslib/test/md5tests/same/multi4.txt b/test/test_roslib/test/md5tests/same/multi4.txt
new file mode 100644
index 00000000..30e80646
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/multi4.txt
@@ -0,0 +1,16 @@
+# short comment about a
+int32 a #a
+# short comment about log
+Log log #log
+#
+# short comment about s
+string s #s
+# short comment about time
+Clock time #time
+# short comment about b
+int32 b #b
+# short comment about d
+duration d #d
+# short comment about t
+time t # t
+
diff --git a/test/test_roslib/test/md5tests/same/multi5.txt b/test/test_roslib/test/md5tests/same/multi5.txt
new file mode 100644
index 00000000..402087fc
--- /dev/null
+++ b/test/test_roslib/test/md5tests/same/multi5.txt
@@ -0,0 +1,8 @@
+int32 a
+roslib/Log log
+
+string s
+roslib/Clock time
+int32 b
+duration d
+ time t
diff --git a/test/test_roslib/test/package.cpp b/test/test_roslib/test/package.cpp
new file mode 100644
index 00000000..3d34b9c3
--- /dev/null
+++ b/test/test_roslib/test/package.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2008, Willow Garage, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Willow Garage, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+
+#include
+#include
+#include
+
+using namespace ros;
+
+TEST(Package, getPath)
+{
+ std::string path = package::getPath("roslib");
+ printf("Path: %s\n", path.c_str());
+ ASSERT_FALSE(path.empty());
+}
+
+TEST(Package, getAll)
+{
+ using package::V_string;
+ V_string packages;
+ ASSERT_TRUE(package::getAll(packages));
+ ASSERT_FALSE(packages.empty());
+
+ V_string::iterator it = packages.begin();
+ V_string::iterator end = packages.end();
+ for (; it != end; ++it)
+ {
+ printf("Package: %s\n", it->c_str());
+ }
+}
+
+int main(int argc, char **argv){
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
diff --git a/test/test_roslib/test/package_tests/p1/bar/manifest.xml b/test/test_roslib/test/package_tests/p1/bar/manifest.xml
new file mode 100644
index 00000000..593b7149
--- /dev/null
+++ b/test/test_roslib/test/package_tests/p1/bar/manifest.xml
@@ -0,0 +1,14 @@
+
+
+
+ bar
+
+
+ Ken Conley
+ BSD
+
+ http://ros.org/wiki/bar
+
+
+
+
diff --git a/test/test_roslib/test/package_tests/p1/foo/manifest.xml b/test/test_roslib/test/package_tests/p1/foo/manifest.xml
new file mode 100644
index 00000000..9ae3220a
--- /dev/null
+++ b/test/test_roslib/test/package_tests/p1/foo/manifest.xml
@@ -0,0 +1,14 @@
+
+
+
+ foo
+
+
+ Ken Conley
+ BSD
+
+ http://ros.org/wiki/foo
+
+
+
+
diff --git a/test/test_roslib/test/package_tests/p2/foo/manifest.xml b/test/test_roslib/test/package_tests/p2/foo/manifest.xml
new file mode 100644
index 00000000..9ae3220a
--- /dev/null
+++ b/test/test_roslib/test/package_tests/p2/foo/manifest.xml
@@ -0,0 +1,14 @@
+
+
+
+ foo
+
+
+ Ken Conley
+ BSD
+
+ http://ros.org/wiki/foo
+
+
+
+
diff --git a/test/test_roslib/test/platform_supported.manifest.xml b/test/test_roslib/test/platform_supported.manifest.xml
new file mode 100644
index 00000000..c7f96722
--- /dev/null
+++ b/test/test_roslib/test/platform_supported.manifest.xml
@@ -0,0 +1,8 @@
+
+
+ Unit tests verifying that roslib is operating as expected.
+
+ none
+ BSD
+
+
diff --git a/test/test_roslib/test/stack_tests/s1/bar/stack.xml b/test/test_roslib/test/stack_tests/s1/bar/stack.xml
new file mode 100644
index 00000000..993c9dc3
--- /dev/null
+++ b/test/test_roslib/test/stack_tests/s1/bar/stack.xml
@@ -0,0 +1,9 @@
+
+
+ bar
+
+ Ken Conley
+ BSD
+
+
+
diff --git a/test/test_roslib/test/stack_tests/s1/foo/stack.xml b/test/test_roslib/test/stack_tests/s1/foo/stack.xml
new file mode 100644
index 00000000..84854266
--- /dev/null
+++ b/test/test_roslib/test/stack_tests/s1/foo/stack.xml
@@ -0,0 +1,9 @@
+
+
+ foo
+
+ Ken Conley
+ BSD
+
+
+
diff --git a/test/test_roslib/test/stack_tests/s2/foo/stack.xml b/test/test_roslib/test/stack_tests/s2/foo/stack.xml
new file mode 100644
index 00000000..c056d8a3
--- /dev/null
+++ b/test/test_roslib/test/stack_tests/s2/foo/stack.xml
@@ -0,0 +1,9 @@
+
+
+ foo
+
+ Ken Conley
+ BSD
+
+
+
diff --git a/test/test_roslib/test/stack_tests2/s3 b/test/test_roslib/test/stack_tests2/s3
new file mode 120000
index 00000000..f8c1ce1f
--- /dev/null
+++ b/test/test_roslib/test/stack_tests2/s3
@@ -0,0 +1 @@
+../stack_tests/s1
\ No newline at end of file
diff --git a/test/test_roslib/test/test_md5sums.py b/test/test_roslib/test/test_md5sums.py
new file mode 100644
index 00000000..b763776b
--- /dev/null
+++ b/test/test_roslib/test/test_md5sums.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2008, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Revision $Id$
+
+import roslib; roslib.load_manifest('test_roslib')
+
+import unittest
+import rosunit
+from test_roslib.msg import *
+
+
+class TestMd5sums(unittest.TestCase):
+
+ def test_field_name_change(self):
+ self.assertNotEquals(FieldNameChange1._md5sum, FieldNameChange2._md5sum)
+
+ def test_type_name_change(self):
+ self.assertEquals(TypeNameChange1._md5sum, TypeNameChange2._md5sum)
+
+ def test_type_name_change_array(self):
+ self.assertEquals(TypeNameChangeArray1._md5sum, TypeNameChangeArray2._md5sum)
+
+ def test_type_name_change_complex(self):
+ self.assertEquals(TypeNameChangeComplex1._md5sum, TypeNameChangeComplex2._md5sum)
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_md5sums', TestMd5sums, coverage_packages=[])
diff --git a/test/test_roslib/test/test_roslib.py b/test/test_roslib/test/test_roslib.py
new file mode 100644
index 00000000..2e130218
--- /dev/null
+++ b/test/test_roslib/test/test_roslib.py
@@ -0,0 +1,61 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import struct
+import sys
+import unittest
+
+import rosunit
+
+class RoslibTest(unittest.TestCase):
+
+ def test_load_manifest(self):
+ # this is a bit of a noop as it's a prerequisite of running with rosunit
+ import roslib
+ roslib.load_manifest('test_roslib')
+
+ def test_interactive(self):
+ import roslib
+ import roslib.scriptutil
+
+ # make sure that it's part of high-level API
+ self.failIf(roslib.is_interactive(), "interactive should be false by default")
+ for v in [True, False]:
+ roslib.set_interactive(v)
+ self.assertEquals(v, roslib.is_interactive())
+ self.assertEquals(v, roslib.scriptutil.is_interactive())
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_roslib_module', RoslibTest, coverage_packages=['roslib'])
+
diff --git a/test/test_roslib/test/test_roslib_exceptions.py b/test/test_roslib/test/test_roslib_exceptions.py
new file mode 100644
index 00000000..fafe8805
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_exceptions.py
@@ -0,0 +1,49 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import struct
+import sys
+import unittest
+
+import rosunit
+
+class RoslibExceptionsTest(unittest.TestCase):
+
+ def test_exceptions(self):
+ from roslib.exceptions import ROSLibException
+ self.assert_(isinstance(ROSLibException(), Exception))
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_exceptions', RoslibExceptionsTest, coverage_packages=['roslib.exceptions'])
+
diff --git a/test/test_roslib/test/test_roslib_genpy.py b/test/test_roslib/test/test_roslib_genpy.py
new file mode 100644
index 00000000..e6193400
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_genpy.py
@@ -0,0 +1,503 @@
+#!/usr/bin/env python
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2008, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Revision $Id$
+
+NAME = 'test_genpy'
+import roslib; roslib.load_manifest('test_roslib')
+
+import sys
+import unittest
+import cStringIO
+import time
+
+import rosunit
+
+# NOTE: roslib.genpy is in the roslib package to prevent circular
+# dependencies on messages in the roslib package
+# (Header/Time/Duration)
+
+class TestGenpy(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ ## Test genpy.reduce_pattern
+ def test_reduce_pattern(self):
+ tests = [
+ ('', ''),
+ ('hhhh', '4h'),
+ ('hhhhi', '4hi'),
+ ('hhhhiiiibbb', '4h4i3b'),
+ ('1h2h3h', '1h2h3h'),
+ ('hIi', 'hIi'),
+ ('66h', '66h'),
+ ('%ss', '%ss'), #don't reduce strings with format chars in them
+ ('',d.xml())
+ self.assertEquals(d, Depend('roslib'))
+ self.assertNotEquals(d, Depend('roslib2'))
+ self.assertNotEquals(d, 1)
+
+ def test_ROSDep(self):
+ from roslib.manifest import ROSDep, ManifestException
+ for bad in [None, '', 1]:
+ try:
+ rd = ROSDep(bad)
+ self.fail("should have failed on [%s]"%bad)
+ except ValueError: pass
+
+ rd = ROSDep('python')
+ self.assertEquals('',rd.xml())
+
+ def test_VersionControl(self):
+ from roslib.manifest import VersionControl, ManifestException
+ ros_svn = 'https://ros.svn.sf.net/svnroot'
+
+ bad = [
+ (None, ros_svn),
+ ('svn', 1),
+ ]
+ for type_, url in bad:
+ try:
+ VersionControl(type_,url)
+ self.fail("should have failed on [%s] [%s]"%(type_, url))
+ except ValueError: pass
+
+ tests = [
+ ('svn', ros_svn, ''%ros_svn),
+ ('cvs', None, ''),
+ ]
+ for type_, url, xml in tests:
+ vc = VersionControl(type_, url)
+ self.assertEquals(type_, vc.type)
+ self.assertEquals(url, vc.url)
+ self.assertEquals(xml, vc.xml())
+
+ def _subtest_parse_example1(self, m):
+ from roslib.manifest import Manifest
+ self.assert_(isinstance(m, Manifest))
+ self.assertEquals("a brief description", m.brief)
+ self.assertEquals("Line 1\nLine 2", m.description.strip())
+ self.assertEquals("The authors\ngo here", m.author.strip())
+ self.assertEquals("Public Domain\nwith other stuff", m.license.strip())
+ self.assertEquals("http://pr.willowgarage.com/package/", m.url)
+ self.assertEquals("http://www.willowgarage.com/files/willowgarage/robot10.jpg", m.logo)
+ dpkgs = [d.package for d in m.depends]
+ self.assertEquals(set(['pkgname', 'common']), set(dpkgs))
+ rdpkgs = [d.name for d in m.rosdeps]
+ self.assertEquals(set(['python', 'bar', 'baz']), set(rdpkgs))
+
+ def test_parse_example1_file(self):
+ from roslib.manifest import parse_file, Manifest
+ p = os.path.join(roslib.packages.get_pkg_dir('test_roslib'), 'test', 'manifest_tests', 'example1.xml')
+ self._subtest_parse_example1(parse_file(p))
+
+ def test_parse_example1_string(self):
+ from roslib.manifest import parse, Manifest
+ self._subtest_parse_example1(parse(EXAMPLE1))
+
+ def test_Manifest_str(self):
+ # just make sure it doesn't crash
+ from roslib.manifest import parse
+ str(parse(EXAMPLE1))
+
+ def test_Manifest_xml(self):
+ from roslib.manifest import parse
+ m = parse(EXAMPLE1)
+ self._subtest_parse_example1(m)
+ # verify roundtrip
+ m2 = parse(m.xml())
+ self._subtest_parse_example1(m2)
+
+
+ def test_parse_bad_file(self):
+ from roslib.manifest import parse_file, Manifest
+ # have to import from ManifestException due to weirdness when run in --cov mode
+ from roslib.manifestlib import ManifestException
+ my_dir = roslib.packages.get_pkg_dir('test_roslib')
+ base_p = os.path.join(my_dir, 'test', 'manifest_tests')
+ for b in ['bad1.xml', 'bad2.xml', 'bad3.xml']:
+ p = os.path.join(base_p, b)
+ try:
+ parse_file(p)
+ self.fail("parse should have failed on bad manifest")
+ except ManifestException, e:
+ print str(e)
+ self.assert_(b in str(e), "file name should be in error message: %s"%(str(e)))
+
+EXAMPLE1 = """
+ Line 1
+Line 2
+
+ The authors
+go here
+ Public Domain
+with other stuff
+ http://pr.willowgarage.com/package/
+ http://www.willowgarage.com/files/willowgarage/robot10.jpg
+
+
+
+
+
+
+
+
+
+"""
+
+
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_manifest', RoslibManifestTest, coverage_packages=['roslib.manifest', 'roslib.manifestlib'])
+
diff --git a/test/test_roslib/test/test_roslib_manifestlib.py b/test/test_roslib/test/test_roslib_manifestlib.py
new file mode 100644
index 00000000..dbd812e9
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_manifestlib.py
@@ -0,0 +1,300 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import struct
+import sys
+import unittest
+
+import rosunit
+
+class RoslibManifestlibTest(unittest.TestCase):
+
+ def test_ManifestException(self):
+ from roslib.manifestlib import ManifestException
+ self.assert_(isinstance(ManifestException(), Exception))
+
+ def test_Platform(self):
+ from roslib.manifestlib import Platform, ManifestException
+ for bad in [None, '', 1]:
+ try:
+ Platform(bad, '1')
+ self.fail("should have failed on [%s]"%bad)
+ except ValueError: pass
+ try:
+ Platform('ubuntu', bad)
+ self.fail("should have failed on [%s]"%bad)
+ except ValueError: pass
+
+ p = Platform('ubuntu', '8.04')
+ self.assertEquals('ubuntu 8.04', str(p))
+ self.assertEquals('ubuntu 8.04', repr(p))
+
+ self.assertEquals('',p.xml())
+ self.assertEquals(p, Platform('ubuntu', '8.04'))
+ self.assertEquals(p, Platform('ubuntu', '8.04', notes=None))
+ self.assertNotEquals(p, Platform('ubuntu', '8.04', 'some notes'))
+ self.assertNotEquals(p, 'foo')
+ self.assertNotEquals(p, 1)
+
+ # note: probably actually "osx"
+ p = Platform('OS X', '10.6', 'macports')
+ self.assertEquals('OS X 10.6', str(p))
+ self.assertEquals('OS X 10.6', repr(p))
+
+ self.assertEquals('',p.xml())
+ self.assertEquals(p, p)
+ self.assertEquals(p, Platform('OS X', '10.6', 'macports'))
+ self.assertNotEquals(p, Platform('OS X', '10.6'))
+ self.assertNotEquals(p, 'foo')
+ self.assertNotEquals(p, 1)
+
+
+ def test_Depend(self):
+ from roslib.manifestlib import Depend, StackDepend, ManifestException
+ for bad in [None, '', 1]:
+ try:
+ Depend(bad)
+ self.fail("should have failed on [%s]"%bad)
+ except ValueError: pass
+
+ d = Depend('roslib')
+ self.assertEquals('roslib', str(d))
+ self.assertEquals('roslib', repr(d))
+
+ self.assertEquals('',d.xml())
+ self.assertEquals(d, Depend('roslib'))
+ self.assertNotEquals(d, StackDepend('roslib'))
+ self.assertNotEquals(d, Depend('roslib2'))
+ self.assertNotEquals(d, 1)
+
+ def test_StackDepend(self):
+ from roslib.manifestlib import Depend, StackDepend, ManifestException
+ for bad in [None, '', 1]:
+ try:
+ StackDepend(bad)
+ self.fail("should have failed on [%s]"%bad)
+ except ValueError: pass
+
+ d = StackDepend('common')
+ self.assertEquals('common', str(d))
+ self.assertEquals('common', repr(d))
+
+ self.assertEquals('',d.xml())
+ self.assertEquals(d, StackDepend('common'))
+ self.assertNotEquals(d, Depend('common'))
+ self.assertNotEquals(d, StackDepend('common2'))
+ self.assertNotEquals(d, 1)
+
+ def test_ROSDep(self):
+ from roslib.manifestlib import ROSDep, ManifestException
+ for bad in [None, '', 1]:
+ try:
+ rd = ROSDep(bad)
+ self.fail("should have failed on [%s]"%bad)
+ except ValueError: pass
+
+ rd = ROSDep('python')
+ self.assertEquals('',rd.xml())
+
+ def test_VersionControl(self):
+ from roslib.manifestlib import VersionControl, ManifestException
+ ros_svn = 'https://ros.svn.sf.net/svnroot'
+
+ bad = [
+ (None, ros_svn),
+ ('svn', 1),
+ ]
+ for type_, url in bad:
+ try:
+ VersionControl(type_,url)
+ self.fail("should have failed on [%s] [%s]"%(type_, url))
+ except ValueError: pass
+
+ tests = [
+ ('svn', ros_svn, ''%ros_svn),
+ ('cvs', None, ''),
+ ]
+ for type_, url, xml in tests:
+ vc = VersionControl(type_, url)
+ self.assertEquals(type_, vc.type)
+ self.assertEquals(url, vc.url)
+ self.assertEquals(xml, vc.xml())
+
+ def _subtest_parse_example1(self, m):
+ from roslib.manifestlib import _Manifest
+ self.assert_(isinstance(m, _Manifest))
+ self.assertEquals("a brief description", m.brief)
+ self.assertEquals("Line 1\nLine 2", m.description.strip())
+ self.assertEquals("The authors\ngo here", m.author.strip())
+ self.assertEquals("Public Domain\nwith other stuff", m.license.strip())
+ self.assertEquals("http://pr.willowgarage.com/package/", m.url)
+ self.assertEquals("http://www.willowgarage.com/files/willowgarage/robot10.jpg", m.logo)
+ dpkgs = [d.package for d in m.depends]
+ self.assertEquals(set(['pkgname', 'common']), set(dpkgs))
+ rdpkgs = [d.name for d in m.rosdeps]
+ self.assertEquals(set(['python', 'bar', 'baz']), set(rdpkgs))
+ for p in m.platforms:
+ if p.os == 'ubuntu':
+ self.assertEquals("8.04", p.version)
+ self.assertEquals('', p.notes)
+ elif p.os == 'OS X':
+ self.assertEquals("10.6", p.version)
+ self.assertEquals("macports", p.notes)
+ else:
+ self.fail("unknown platform "+str(p))
+
+ def _subtest_parse_stack_example1(self, m):
+ from roslib.manifestlib import _Manifest
+ self.assert_(isinstance(m, _Manifest))
+ self.assertEquals('stack', m._type)
+ self.assertEquals("a brief description", m.brief)
+ self.assertEquals("Line 1\nLine 2", m.description.strip())
+ self.assertEquals("The authors\ngo here", m.author.strip())
+ self.assertEquals("Public Domain\nwith other stuff", m.license.strip())
+ self.assertEquals("http://ros.org/stack/", m.url)
+ self.assertEquals("http://www.willowgarage.com/files/willowgarage/robot10.jpg", m.logo)
+ dpkgs = [d.stack for d in m.depends]
+ self.assertEquals(set(['stackname', 'common']), set(dpkgs))
+ self.assertEquals([], m.rosdeps)
+ self.assertEquals([], m.exports)
+
+ def test_parse_example1_file(self):
+ from roslib.manifestlib import parse_file, _Manifest
+ p = os.path.join(roslib.packages.get_pkg_dir('test_roslib'), 'test', 'manifest_tests', 'example1.xml')
+ self._subtest_parse_example1(parse_file(_Manifest(), p))
+
+ p = os.path.join(roslib.packages.get_pkg_dir('test_roslib'), 'test', 'manifest_tests', 'stack_example1.xml')
+ self._subtest_parse_stack_example1(parse_file(_Manifest('stack'), p))
+
+ def test_parse_example1_string(self):
+ from roslib.manifestlib import parse, _Manifest
+ self._subtest_parse_example1(parse(_Manifest(), EXAMPLE1))
+ self._subtest_parse_stack_example1(parse(_Manifest('stack'), STACK_EXAMPLE1))
+
+ def test__Manifest(self):
+ from roslib.manifestlib import _Manifest
+ m = _Manifest()
+ # check defaults
+ self.assertEquals('package', m._type)
+ m = _Manifest('stack')
+ self.assertEquals('stack', m._type)
+
+ def test_Manifest_str(self):
+ # just make sure it doesn't crash
+ from roslib.manifestlib import parse, _Manifest
+ str(parse(_Manifest(), EXAMPLE1))
+
+ def test_Manifest_xml(self):
+ from roslib.manifestlib import parse, _Manifest
+ m = _Manifest()
+ parse(m, EXAMPLE1)
+ self._subtest_parse_example1(m)
+ # verify roundtrip
+ m2 = _Manifest()
+ parse(m2, m.xml())
+ self._subtest_parse_example1(m2)
+
+ # bad file examples should be more like the roslaunch tests where there is just 1 thing wrong
+ def test_parse_bad_file(self):
+ from roslib.manifestlib import parse_file, _Manifest, ManifestException
+ my_dir = roslib.packages.get_pkg_dir('test_roslib')
+ base_p = os.path.join(my_dir, 'test', 'manifest_tests')
+ m = _Manifest()
+ for b in ['bad1.xml', 'bad2.xml', 'bad3.xml']:
+ p = os.path.join(base_p, b)
+ try:
+ parse_file(m, p)
+ self.fail("parse should have failed on bad manifest")
+ except ManifestException, e:
+ print str(e)
+ self.assert_(b in str(e), "file name should be in error message [%s]"%(str(e)))
+
+EXAMPLE1 = """
+ Line 1
+Line 2
+
+ The authors
+go here
+ Public Domain
+with other stuff
+ http://pr.willowgarage.com/package/
+ http://www.willowgarage.com/files/willowgarage/robot10.jpg
+
+
+
+
+
+
+
+
+
+
+
+"""
+
+STACK_EXAMPLE1 = """
+ Line 1
+Line 2
+
+ The authors
+go here
+ Public Domain
+with other stuff
+ http://ros.org/stack/
+ http://www.willowgarage.com/files/willowgarage/robot10.jpg
+
+
+"""
+
+STACK_INVALID1 = """
+ Line 1
+ The authors
+ Public Domain
+
+"""
+
+STACK_INVALID2 = """
+ Line 1
+ The authors
+ Public Domain
+
+
+
+
+"""
+
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_manifest', RoslibManifestlibTest, coverage_packages=['roslib.manifestlib'])
+
diff --git a/test/test_roslib/test/test_roslib_message.py b/test/test_roslib/test/test_roslib_message.py
new file mode 100644
index 00000000..8d11ac85
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_message.py
@@ -0,0 +1,564 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import sys
+import time
+import unittest
+import traceback
+
+import roslib.message
+import rosunit
+
+# Not much to test, just tripwires
+
+class MessageTest(unittest.TestCase):
+
+ def test_check_types_Header(self):
+ # #2128: test that check_types works with a Header
+ # #message. This is a weird case because Header has an aliased
+ # #type and is the only ROS type for which that is true
+ from test_roslib.msg import HeaderTest
+ x = HeaderTest()
+ x._check_types()
+
+ def test_Message_check_types(self):
+ # test on a generated message
+ # - use UInt16MultiArray because it has an embedded MultiArrayLayout
+ from std_msgs.msg import String, UInt16MultiArray, MultiArrayLayout, MultiArrayDimension
+ from roslib.message import SerializationError
+ # not checking overflow in this test
+ correct = [String(), String('foo'), String(''), String(data='data'),
+ UInt16MultiArray(),
+ UInt16MultiArray(MultiArrayLayout(), []),
+ UInt16MultiArray(MultiArrayLayout(data_offset=1), [1, 2, 3]),
+ UInt16MultiArray(layout=MultiArrayLayout(data_offset=1)),
+ UInt16MultiArray(layout=MultiArrayLayout(dim=[])),
+ UInt16MultiArray(layout=MultiArrayLayout(dim=[MultiArrayDimension()])),
+ UInt16MultiArray(data=[1, 2, 3]),
+ ]
+ for t in correct:
+ t._check_types()
+ for t in correct:
+ try:
+ t._check_types(exc=Exception())
+ self.fail("should have raised wrapped exc")
+ except SerializationError:
+ pass
+
+ wrong = [String(1), String(data=1),
+ UInt16MultiArray(1, []),
+ UInt16MultiArray(MultiArrayLayout(), 1),
+ UInt16MultiArray(String(), []),
+ UInt16MultiArray(layout=MultiArrayLayout(dim=[1])),
+ UInt16MultiArray(layout=MultiArrayLayout(data_offset='')),
+ ]
+ for t in wrong:
+ try:
+ t._check_types()
+ self.fail("should have raised")
+ except SerializationError:
+ pass
+
+ def test_Message(self):
+ import cStringIO
+ from roslib.message import Message, SerializationError
+ self.assert_(isinstance(Message(), Message))
+ m = Message()
+ b = cStringIO.StringIO()
+ m.serialize(b)
+ m.deserialize('')
+
+ # test args/keywords constructor
+ try:
+ Message(1, 2, 3, one=1, two=2, three=3)
+ self.fail("Message should not allow *args and **kwds")
+ except TypeError: pass
+ try:
+ Message()._get_types()
+ self.fail("_get_types() should not be callable on abstract Message instance")
+ except: pass
+
+ # test Empty message
+ class M1(Message):
+ __slots__ = []
+ def __init__(self, *args, **kwds):
+ super(M1, self).__init__(*args, **kwds)
+ def _get_types(self): return []
+
+ # - test __str__ on empty
+ self.assertEquals('', str(M1()))
+ # - should not fail on default constructor
+ M1()._check_types()
+ # - must fail if provided an exception
+ try:
+ M1()._check_types(Exception("test"))
+ self.fail("_check_types must fail if explicitly provided an exception")
+ except SerializationError: pass
+
+ # Test simple message with two fields
+ class M2(Message):
+ __slots__ = ['a', 'b']
+ def _get_types(self): return ['int32', 'int32']
+ def __init__(self, *args, **kwds):
+ super(M2, self).__init__(*args, **kwds)
+ self.assertEquals('a: 1\nb: 2', str(M2(1, 2)))
+ # - test check types with two int type
+ M2(1, 2)._check_types()
+ M2(a=1, b=2)._check_types()
+ invalid = [M2(a=1), M2('1', '2'), M2(1, '2'), M2(1., 2.), M2(None, 2)]
+ for m in invalid:
+ try:
+ m._check_types()
+ self.fail("check_types for %s should have failed"%m)
+ except SerializationError: pass
+
+
+ valid = [
+ ((), {}, M1),
+ ((), {}, M2),
+ ((1, 2), {}, M2),
+ ((), {'a': 1, 'b': 2}, M2),
+ ((), {'a': 1}, M2),((), {'b': 2}, M2),
+ ]
+ invalid = [
+ ((1,), {}, M1),
+ ((), {'one': 1}, M1),
+ ((1), {}, M2),((1, 2, 3), {}, M2),
+ ((), {'c': 1}, M2),((), {'a': 1, 'b': 2, 'c': 1}, M2),
+ ]
+ for args, kwds, cls in valid:
+ cls(*args, **kwds)
+ val = time.time()
+ val2 = time.time()
+ self.assertEquals(val, M2(val, 2).a)
+ self.assertEquals(val, M2(1, val).b)
+ self.assertEquals(val, M2(a=val).a)
+ self.assertEquals(None, M2(a=val).b)
+ self.assertEquals(None, M2(b=val).a)
+ self.assertEquals(val, M2(b=val).b)
+ self.assertEquals(val, M2(a=val, b=val2).a)
+ self.assertEquals(val2, M2(a=val, b=val2).b)
+ for args, kwds, cls in invalid:
+ try:
+ cls(*args, **kwds)
+ self.fail("Message should have failed for cls[%s] *args[%s] and **kwds[%s]"%(cls, args, kwds))
+ except: pass
+
+ def test_strify_message(self):
+ # this is a bit overtuned, but it will catch regressions
+ from roslib.message import Message, strify_message
+ class M1(Message):
+ __slots__ = []
+ def __init__(self): pass
+ self.assertEquals('', strify_message(M1()))
+ class M2(Message):
+ __slots__ = ['str', 'int', 'float', 'bool', 'list']
+ def __init__(self, str_, int_, float_, bool_, list_):
+ self.str = str_
+ self.int = int_
+ self.float = float_
+ self.bool = bool_
+ self.list = list_
+
+ self.assertEquals("""str: string
+int: 123456789101112
+float: 5678.0
+bool: True
+list: [1, 2, 3]""", strify_message(M2('string', 123456789101112, 5678., True, [1,2,3])))
+
+ self.assertEquals("""str: ''
+int: -1
+float: 0.0
+bool: False
+list: []""", strify_message(M2('', -1, 0., False, [])))
+
+ class M3(Message):
+ __slots__ = ['m2']
+ def __init__(self, m2):
+ self.m2 = m2
+ self.assertEquals("""m2:
+ str: string
+ int: -1
+ float: 0.0
+ bool: False
+ list: []""", strify_message(M3(M2('string', -1, 0., False, []))))
+
+ # test array of Messages field
+ class M4(Message):
+ __slots__ = ['m2s']
+ def __init__(self, m2s):
+ self.m2s = m2s
+
+ self.assertEquals("""m2s:
+ -
+ str: string
+ int: 1234
+ float: 5678.0
+ bool: True
+ list: [1, 2, 3]
+ -
+ str: string
+ int: -1
+ float: 0.0
+ bool: False
+ list: []""", strify_message(M4([
+ M2('string', 1234, 5678., True, [1,2,3]),
+ M2('string', -1, 0., False, []),
+ ])))
+ # test Time and Duration
+ from roslib.rostime import Time, Duration
+ class M5(Message):
+ __slots__ = ['t', 'd']
+ def __init__(self, t, d):
+ self.t = t
+ self.d = d
+ self.assertEquals("""t:
+ secs: 987
+ nsecs: 654
+d:
+ secs: 123
+ nsecs: 456""", strify_message(M5(Time(987, 654), Duration(123, 456))))
+
+ # test final clause of strify -- str anything that isn't recognized
+ self.assertEquals("set([1])", strify_message(set([1])))
+
+ def test_strify_yaml(self):
+ import yaml
+ def roundtrip(m):
+ yaml_text = strify_message(m)
+ print yaml_text
+ loaded = yaml.load(yaml_text)
+ print "loaded", loaded
+ new_inst = m.__class__()
+ if loaded is not None:
+ fill_message_args(new_inst, [loaded])
+ else:
+ fill_message_args(new_inst, [])
+ return new_inst
+
+ # test YAML roundtrip. strify_message doesn't promise this
+ # yet, but want to use it in this way in some demo toolchains
+ from roslib.message import Message, strify_message, fill_message_args
+ class M1(Message):
+ __slots__ = []
+ def __init__(self): pass
+ self.assertEquals(M1(), roundtrip(M1()))
+
+ class M2(Message):
+ __slots__ = ['str', 'int', 'float', 'bool', 'list']
+ def __init__(self, str_=None, int_=None, float_=None, bool_=None, list_=None):
+ self.str = str_
+ self.int = int_
+ self.float = float_
+ self.bool = bool_
+ self.list = list_
+
+ val = M2('string', 123456789101112, 5678., True, [1,2,3])
+ self.assertEquals(val, roundtrip(val))
+ # test with empty string and empty list
+ val = M2('', -1, 0., False, [])
+ self.assertEquals(val, roundtrip(val))
+
+ class M3(Message):
+ __slots__ = ['m2']
+ def __init__(self, m2=None):
+ self.m2 = m2 or M2()
+
+ val = M3(M2('string', -1, 0., False, []))
+ self.assertEquals(val, roundtrip(val))
+
+ # test array of Messages field. We can't use M4 or M5 because fill_message_args has to instantiate the embedded type
+ from test_roslib.msg import ArrayOfMsgs
+ from std_msgs.msg import String, Time, MultiArrayLayout, MultiArrayDimension
+ dims1 = [MultiArrayDimension(*args) for args in [('', 0, 0), ('x', 1, 2), ('y of z', 3, 4)]]
+ dims2 = [MultiArrayDimension('hello world', 91280, 1983274)]
+ times = [Time(roslib.rostime.Time(*args)) for args in [(0,), (12345, 6789), (1, 1)]]
+ val = ArrayOfMsgs([String(''), String('foo'), String('bar of soap')],
+ times,
+ [MultiArrayLayout(dims1, 0), MultiArrayLayout(dims2, 12354)],
+ )
+ self.assertEquals(val, roundtrip(val))
+
+
+ def test_ServiceDefinition(self):
+ from roslib.message import ServiceDefinition
+ self.assert_(isinstance(ServiceDefinition(), ServiceDefinition))
+
+ def test_check_type(self):
+ # check_type() currently does not do harder checks like
+ # type-checking class types. as soon as it does, it will need
+ # test to validate this.
+ from roslib.message import check_type, SerializationError
+ from roslib.rostime import Time, Duration
+ valids = [
+ ('byte', 1), ('byte', -1),
+ ('string', ''), ('string', 'a string of text'),
+ ('int32[]', []),
+ ('int32[]', [1, 2, 3, 4]),
+ ('time', Time()), ('time', Time.from_seconds(1.0)),
+ ('time', Time(10000)), ('time', Time(1000, -100)),
+ ('duration', Duration()),('duration', Duration()),
+ ('duration', Duration(100)), ('duration', Duration(-100, -100)),
+ ]
+
+ for t, v in valids:
+ try:
+ check_type('n', t, v)
+ except Exception, e:
+ traceback.print_exc()
+ raise Exception("failure type[%s] value[%s]: %s"%(t, v, str(e)))
+
+ invalids = [
+ ('byte', 129), ('byte', -129), ('byte', 'byte'), ('byte', 1.0),
+ ('string', 1),
+ ('uint32', -1),
+ ('int8', 112312), ('int8', -112312),
+ ('uint8', -1), ('uint8', 112312),
+ ('int32', '1'), ('int32', 1.),
+ ('int32[]', 1), ('int32[]', [1., 2.]), ('int32[]', [1, 2.]),
+ ('duration', 1), ('time', 1),
+ ]
+ for t, v in invalids:
+ try:
+ check_type('n', t, v)
+ self.fail("check_type[%s, %s] should have failed"%(t, v))
+ except SerializationError: pass
+
+ def test_get_message_class(self):
+ from roslib.message import get_message_class
+
+ try:
+ self.assertEquals(None, get_message_class('String'))
+ self.fail("should have thrown ValueError")
+ except ValueError: pass
+ # non-existent package
+ self.assertEquals(None, get_message_class('fake/Fake'))
+ # non-existent message
+ self.assertEquals(None, get_message_class('roslib/Fake'))
+ # package with no messages
+ self.assertEquals(None, get_message_class('genmsg_cpp/Fake'))
+
+ import roslib.msg
+ self.assertEquals(roslib.msg.Header, get_message_class('Header'))
+ self.assertEquals(roslib.msg.Header, get_message_class('roslib/Header'))
+ self.assertEquals(roslib.msg.Log, get_message_class('roslib/Log'))
+
+ def test_fill_message_args_embed_time(self):
+ from roslib.rostime import Time, Duration
+ from roslib.message import fill_message_args
+ from test_roslib.msg import FillEmbedTime
+
+ # test fill_message_args with embeds and time vals
+ # time t
+ # duration d
+ # std_msgs/String str_msg
+ # std_msgs/String[] str_msg_array
+ # int32 i32
+
+ tests = [
+
+ ]
+ m = FillEmbedTime()
+ fill_message_args(m, [{}])
+ self.assertEquals(m.t, Time())
+ self.assertEquals(m.d, Duration())
+ self.assertEquals(m.str_msg.data, '')
+ self.assertEquals(m.str_msg_array, [])
+ self.assertEquals(m.i32, 0)
+
+ # list tests
+ # - these should be equivalent
+ equiv = [
+ [[10, 20], [30, 40], ['foo'], [['bar'], ['baz']], 32],
+ [{'secs': 10, 'nsecs': 20}, {'secs': 30, 'nsecs': 40}, ['foo'], [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40], {'data': 'foo'}, [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40], ['foo'], [{'data': 'bar'}, {'data': 'baz'}], 32],
+
+ [{'t': [10, 20], 'd': [30, 40], 'str_msg': {'data': 'foo'}, 'str_msg_array': [{'data': 'bar'}, {'data': 'baz'}], 'i32': 32}],
+ [{'t': {'secs': 10, 'nsecs': 20}, 'd': [30, 40], 'str_msg': {'data': 'foo'}, 'str_msg_array': [{'data': 'bar'}, {'data': 'baz'}], 'i32': 32}],
+ ]
+ for test in equiv:
+ m = FillEmbedTime()
+ try:
+ fill_message_args(m, test)
+ except Exception, e:
+ self.fail("failed to fill with : %s\n%s"%(str(test), traceback.format_exc()))
+
+ self.assertEquals(m.t, Time(10, 20))
+ self.assertEquals(m.d, Duration(30, 40))
+ self.assertEquals(m.str_msg.data, 'foo')
+ self.assertEquals(len(m.str_msg_array), 2, m.str_msg_array)
+ self.assertEquals(m.str_msg_array[0].data, 'bar')
+ self.assertEquals(m.str_msg_array[1].data, 'baz')
+ self.assertEquals(m.i32, 32)
+ # test creation of Time/Duration from single number representation, which is necessary for
+
+ # yaml single-number support
+ # - cannot include in tests above as conversion from integer is lossy
+ m = FillEmbedTime()
+ fill_message_args(m, [10000000020, 30000000040, ['foo'], [['bar'], ['baz']], 32])
+ self.assertEquals(10, m.t.secs)
+ self.assert_(abs(20 - m.t.nsecs) < 2)
+ self.assertEquals(30, m.d.secs)
+ self.assert_(abs(40 - m.d.nsecs) < 2)
+ self.assertEquals(len(m.str_msg_array), 2, m.str_msg_array)
+ self.assertEquals(m.str_msg_array[0].data, 'bar')
+ self.assertEquals(m.str_msg_array[1].data, 'baz')
+ self.assertEquals(m.i32, 32)
+
+ bad = [
+ # underfill in sub-args
+ [[10, 20], [30, 40], ['foo'], [['bar'], ['baz']]],
+ [[10], [30, 40], ['foo'], [['bar'], ['baz']], 32],
+ [[10, 20], [30], ['foo'], [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40], [], [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40], ['foo'], [['bar'], []], 32],
+
+ # overfill
+ [[10, 20], [30, 40], ['foo'], [['bar'], ['baz']], 32, 64],
+ [[10, 20, 30], [30, 40], ['foo'], [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40, 50], ['foo'], [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40], ['foo', 'bar'], [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40], ['foo'], [['bar', 'baz'], ['baz']], 32],
+ [[10, 20], [30, 40], ['foo'], [['bar'], ['baz', 'car']], 32],
+
+ # invalid fields
+ [{'secs': 10, 'nsecs': 20, 'foo': 1}, {'secs': 30, 'nsecs': 40}, ['foo'], [['bar'], ['baz']], 32],
+ [{'secs': 10, 'nsecs': 20}, {'secs': 30, 'nsecs': 40, 'foo': 1}, ['foo'], [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40], {'data': 'foo', 'fata': 1}, [['bar'], ['baz']], 32],
+ [[10, 20], [30, 40], ['foo'], [{'data': 'bar'}, {'beta': 'baz'}], 32],
+ [{'t': [10, 20], 'd': [30, 40], 'str_msg': {'data': 'foo'}, 'str_msg_array': [{'data': 'bar'}, {'data': 'baz'}], 'i32': 32, 'i64': 64}],
+ ]
+ for b in bad:
+ failed = True
+ try:
+ m = FillEmbedTime()
+ fill_message_args(m, b)
+ except roslib.message.ROSMessageException:
+ failed = False
+ self.failIf(failed, "fill_message_args should have failed: %s"%str(b))
+
+
+
+ def test_fill_message_args_simple(self):
+ from roslib.message import fill_message_args
+ from test_roslib.msg import FillSimple
+ #int32 i32
+ #string str
+ #int32[] i32_array
+ #bool b
+
+ for v in [[], {}]:
+ try:
+ fill_message_args(object(), v)
+ self.fail("should have raised ValueError")
+ except ValueError: pass
+ try:
+ m = FillSimple()
+ # call underlying routine as the branch is not reachable from above
+ roslib.message._fill_message_args(m, 1, {}, '')
+ self.fail("should have raised ValueError for bad msg_args")
+ except ValueError: pass
+
+ simple_tests = [
+ [1, 'foo', [], True],
+ [1, 'foo', [1, 2, 3, 4], False],
+ ]
+ for test in simple_tests:
+ m = FillSimple()
+ fill_message_args(m, test)
+ self.assertEquals(m.i32, test[0])
+ self.assertEquals(m.str, test[1])
+ self.assertEquals(m.i32_array, test[2])
+ self.assertEquals(m.b, test[3])
+
+ # test with dictionaries
+ m = FillSimple()
+ fill_message_args(m, [{}])
+ self.assertEquals(m.i32, 0)
+ self.assertEquals(m.str, '')
+ self.assertEquals(m.i32_array, [])
+ self.assertEquals(m.b, False)
+
+ m = FillSimple()
+ fill_message_args(m, [{'i32': 10}])
+ self.assertEquals(m.i32, 10)
+ self.assertEquals(m.str, '')
+ self.assertEquals(m.i32_array, [])
+ self.assertEquals(m.b, False)
+
+ m = FillSimple()
+ fill_message_args(m, [{'str': 'hello', 'i32_array': [1, 2, 3]}])
+ self.assertEquals(m.i32, 0)
+ self.assertEquals(m.str, 'hello')
+ self.assertEquals(m.i32_array, [1, 2, 3])
+ self.assertEquals(m.b, False)
+
+ # fill_message_args currently does not type check
+ bad = [
+ # extra key
+ [{'bad': 1, 'str': 'hello', 'i32_array': [1, 2, 3]}],
+ # underfill
+ [1, 'foo', [1, 2, 3]],
+ # overfill
+ [1, 'foo', [1, 2, 3], True, 1],
+ # non-list value for list field
+ [1, 'foo', 1, True],
+ ]
+ for b in bad:
+ failed = True
+ try:
+ m = FillSimple()
+ fill_message_args(m, b)
+ except roslib.message.ROSMessageException:
+ failed = False
+ self.failIf(failed, "fill_message_args should have failed: %s"%str(b))
+
+
+ def test_get_service_class(self):
+ from roslib.message import get_service_class
+
+ # non-existent package
+ self.assertEquals(None, get_service_class('fake/Fake'))
+ # non-existent message
+ self.assertEquals(None, get_service_class('roslib/Fake'))
+ # package with no messages
+ self.assertEquals(None, get_service_class('genmsg_cpp/Fake'))
+
+ import std_srvs.srv
+ self.assertEquals(std_srvs.srv.Empty, get_service_class('std_srvs/Empty'))
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_message', MessageTest, coverage_packages=['roslib.message'])
+
diff --git a/test/test_roslib/test/test_roslib_msgs.py b/test/test_roslib/test/test_roslib_msgs.py
new file mode 100644
index 00000000..5befdac2
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_msgs.py
@@ -0,0 +1,340 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import sys
+import unittest
+
+import roslib.msgs
+import rosunit
+
+class MsgSpecTest(unittest.TestCase):
+
+ def test_verbose(self):
+ self.failIf(roslib.msgs.is_verbose())
+ roslib.msgs.set_verbose(True)
+ self.assert_(roslib.msgs.is_verbose())
+ roslib.msgs.set_verbose(False)
+ self.failIf(roslib.msgs.is_verbose())
+
+ def test_base_msg_type(self):
+ tests = [(None, None), ('String', 'String'), ('std_msgs/String', 'std_msgs/String'),
+ ('String[10]', 'String'), ('string[10]', 'string'), ('std_msgs/String[10]', 'std_msgs/String'),
+ ]
+ for val, res in tests:
+ self.assertEquals(res, roslib.msgs.base_msg_type(val))
+
+ def test_resolve_type(self):
+ from roslib.msgs import resolve_type
+ for t in ['string', 'string[]', 'string[14]', 'int32', 'int32[]']:
+ bt = roslib.msgs.base_msg_type(t)
+ self.assertEquals(t, resolve_type(t, 'test_roslib'))
+
+ self.assertEquals('foo/string', resolve_type('foo/string', 'test_roslib'))
+ self.assertEquals('std_msgs/Header', resolve_type('Header', 'roslib'))
+ self.assertEquals('std_msgs/Header', resolve_type('std_msgs/Header', 'roslib'))
+ self.assertEquals('std_msgs/Header', resolve_type('Header', 'stereo_msgs'))
+ self.assertEquals('std_msgs/String', resolve_type('String', 'std_msgs'))
+ self.assertEquals('std_msgs/String', resolve_type('std_msgs/String', 'std_msgs'))
+ self.assertEquals('std_msgs/String', resolve_type('std_msgs/String', 'test_roslib'))
+ self.assertEquals('std_msgs/String[]', resolve_type('std_msgs/String[]', 'test_roslib'))
+
+ def test_parse_type(self):
+ tests = [
+ ('a', ('a', False, None)),
+ ('int8', ('int8', False, None)),
+ ('std_msgs/String', ('std_msgs/String', False, None)),
+ ('a[]', ('a', True, None)),
+ ('int8[]', ('int8', True, None)),
+ ('std_msgs/String[]', ('std_msgs/String', True, None)),
+ ('a[1]', ('a', True, 1)),
+ ('int8[1]', ('int8', True, 1)),
+ ('std_msgs/String[1]', ('std_msgs/String', True, 1)),
+ ('a[11]', ('a', True, 11)),
+ ('int8[11]', ('int8', True, 11)),
+ ('std_msgs/String[11]', ('std_msgs/String', True, 11)),
+ ]
+ for val, res in tests:
+ self.assertEquals(res, roslib.msgs.parse_type(val))
+
+ fail = ['a[1][2]', 'a[][]', '', None, 'a[', 'a[[1]', 'a[1]]']
+ for f in fail:
+ try:
+ roslib.msgs.parse_type(f)
+ self.fail("should have failed on " +f)
+ except roslib.msgs.MsgSpecException, e: pass
+
+ def test_Constant(self):
+ import random
+ vals = [random.randint(0, 1000) for i in xrange(0, 3)]
+ type_, name, val = [str(x) for x in vals]
+ x = roslib.msgs.Constant(type_, name, val, str(val))
+ self.assertEquals(type_, x.type)
+ self.assertEquals(name, x.name)
+ self.assertEquals(val, x.val)
+ self.assertEquals(roslib.msgs.Constant(type_, name, val, str(val)), x)
+
+ self.assertNotEquals(1, x)
+ self.assertNotEquals(roslib.msgs.Constant('baz', name, val, str(val)), x)
+ self.assertNotEquals(roslib.msgs.Constant(type_, 'foo', val, str(val)), x)
+ self.assertNotEquals(roslib.msgs.Constant(type_, name, 'foo', 'foo'), x)
+
+ try:
+ roslib.msgs.Constant(None, name, val, str(val))
+ except: pass
+ try:
+ roslib.msgs.Constant(type_, None, val, str(val))
+ except: pass
+ try:
+ roslib.msgs.Constant(type_, name, None, 'None')
+ except: pass
+ try:
+ roslib.msgs.Constant(type_, name, val, None)
+ except: pass
+
+ try:
+ x.foo = 'bar'
+ self.fail('Constant should not allow arbitrary attr assignment')
+ except: pass
+
+ def test_MsgSpec(self):
+ def sub_test_MsgSpec(types, names, constants, text, has_header):
+ m = MsgSpec(types, names, constants, text)
+ self.assertEquals(m.types, types)
+ self.assertEquals(m.names, names)
+ self.assertEquals(m.text, text)
+ self.assertEquals(has_header, m.has_header())
+ self.assertEquals(m.constants, constants)
+ self.assertEquals(zip(types, names), m.fields())
+ self.assertEquals(m, MsgSpec(types, names, constants, text))
+ return m
+
+ from roslib.msgs import MsgSpec
+ # allow empty msg
+ empty = sub_test_MsgSpec([], [], [], '', False)
+ self.assertEquals([], empty.fields())
+
+ # one-field
+ one_field = sub_test_MsgSpec(['int32'], ['x'], [], 'int32 x', False)
+ # make sure that equals tests every declared field
+ self.assertEquals(one_field, MsgSpec(['int32'], ['x'], [], 'int32 x'))
+ self.assertNotEquals(one_field, MsgSpec(['uint32'], ['x'], [], 'int32 x'))
+ self.assertNotEquals(one_field, MsgSpec(['int32'], ['y'], [], 'int32 x'))
+ self.assertNotEquals(one_field, MsgSpec(['int32'], ['x'], [], 'uint32 x'))
+ # test against __ne__ as well
+ self.assert_(one_field != MsgSpec(['int32'], ['x'], [], 'uint32 x'))
+
+ # test variations of multiple fields and headers
+ two_fields = sub_test_MsgSpec(['int32', 'string'], ['x', 'str'], [], 'int32 x\nstring str', False)
+ one_header = sub_test_MsgSpec(['Header'], ['header'], [], 'Header header', True)
+ header_and_fields = sub_test_MsgSpec(['Header', 'int32', 'string'], ['header', 'x', 'str'], [], 'Header header\nint32 x\nstring str', True)
+ embed_types = sub_test_MsgSpec(['Header', 'std_msgs/Int32', 'string'], ['header', 'x', 'str'], [], 'Header header\nstd_msgs/Int32 x\nstring str', True)
+
+ # types and names mismatch
+ try:
+ MsgSpec(['int32', 'int32'], ['intval'], [], 'int32 intval\int32 y')
+ self.fail("types and names must align")
+ except: pass
+
+ # test (not) equals against non msgspec
+ self.failIf(one_field == 1)
+ self.assert_(one_field != 1)
+ #TODO: test flatten
+
+ # test that repr doesn't throw an error
+ [repr(x) for x in [empty, one_field, one_header, two_fields, embed_types]]
+
+ def test_init(self):
+ roslib.msgs._initialized = False
+ roslib.msgs._init()
+ self.assert_(roslib.msgs._initialized)
+ # test repeated initialization
+ roslib.msgs._init()
+
+ def test___convert_val(self):
+ from roslib.msgs import _convert_val, MsgSpecException
+ self.assertEquals(0., _convert_val('float32', '0.0'))
+ self.assertEquals(0., _convert_val('float64', '0.0'))
+
+ self.assertEquals('fo o', _convert_val('string', ' fo o '))
+
+ self.assertEquals(1, _convert_val('byte', '1'))
+ self.assertEquals(1, _convert_val('char', '1'))
+ self.assertEquals(1, _convert_val('int8', '1'))
+ self.assertEquals(12, _convert_val('int16', '12'))
+ self.assertEquals(-13, _convert_val('int32', '-13'))
+ self.assertEquals(14, _convert_val('int64', '14'))
+ self.assertEquals(0, _convert_val('uint8', '0'))
+ self.assertEquals(18, _convert_val('uint16', '18'))
+ self.assertEquals(19, _convert_val('uint32', '19'))
+ self.assertEquals(20, _convert_val('uint64', '20'))
+
+ width_fail = [('int8', '129'), ('uint8', '256'),
+ ('int16', '35536'), ('uint16', '-1'),('uint16', '65536'),
+ ('int32', '3000000000'),('int32', '-2700000000'),
+ ('uint32', '-1'),('uint32', '41000000000'),
+ ('uint64', '-1')]
+ for t, v in width_fail:
+ try:
+ _convert_val(t, v)
+ self.fail("should have failed width check: %s, %s"%(t, v))
+ except MsgSpecException: pass
+ type_fail = [('int32', 'f'), ('float32', 'baz')]
+ for t, v in type_fail:
+ try:
+ _convert_val(t, v)
+ self.fail("should have failed type check: %s, %s"%(t, v))
+ except ValueError: pass
+ try:
+ _convert_val('foo', '1')
+ self.fail("should have failed invalid type")
+ except MsgSpecException: pass
+
+ def test_load_package_dependencies(self):
+ # in order to do this test, we have to observe some inner state
+ roslib.msgs.reinit()
+ self.failIf('test_roslib' in roslib.msgs._loaded_packages)
+ self.failIf('std_msgs' in roslib.msgs._loaded_packages)
+ roslib.msgs.load_package_dependencies('test_roslib')
+
+ self.assert_('std_msgs' in roslib.msgs._loaded_packages, roslib.msgs._loaded_packages)
+ # should load deps only, not package itself
+ self.failIf('test_roslib' in roslib.msgs._loaded_packages)
+
+ spec = roslib.msgs.get_registered('std_msgs/String')
+ self.assert_('data' in spec.names) # make sure we have an actual std_msgs msg
+
+ # we don't have a test that properly exercises the recursive
+ # differences, but we need to at least test that branch of code
+ roslib.msgs.reinit()
+ self.failIf('test_roslib' in roslib.msgs._loaded_packages)
+ self.failIf('std_msgs' in roslib.msgs._loaded_packages)
+ roslib.msgs.load_package_dependencies('test_roslib', load_recursive=True)
+ self.assert_('std_msgs' in roslib.msgs._loaded_packages, roslib.msgs._loaded_packages)
+ # should load deps only, not package itself
+ self.failIf('test_roslib' in roslib.msgs._loaded_packages)
+
+ spec = roslib.msgs.get_registered('std_msgs/String')
+ self.assert_('data' in spec.names) # make sure we have an actual std_msgs msg
+
+ def test_load_package(self):
+ # in order to do this test, we have to observe some inner state
+ roslib.msgs.reinit()
+ self.failIf('test_roslib' in roslib.msgs._loaded_packages)
+ self.failIf('std_msgs' in roslib.msgs._loaded_packages)
+ roslib.msgs.load_package('test_roslib')
+
+ self.assert_('test_roslib' in roslib.msgs._loaded_packages)
+ # - shouldn't load deps
+ self.failIf('std_msgs' in roslib.msgs._loaded_packages, roslib.msgs._loaded_packages)
+
+ self.failIf(roslib.msgs.is_registered('std_msgs/String'))
+ spec = roslib.msgs.get_registered('test_roslib/FillSimple')
+ self.assertEquals(['i32', 'str', 'i32_array', 'b'], spec.names) # make sure we have an actual msg
+
+ def test_list_msg_types(self):
+ # can only validly test with roslib, but we test with std_msgs anyways
+ types1 = roslib.msgs.list_msg_types('roslib', False)
+ types2 = roslib.msgs.list_msg_types('roslib', True)
+
+ self.assert_('Header' in types1, types1)
+ self.assert_('Clock' in types1, types1)
+ self.assert_('Log' in types1, types1)
+
+ # roslib has no deps, so this should be equivalent
+ self.assertEquals(types1, types2)
+
+ #TODO: need a real test with dependencies
+ types1 = roslib.msgs.list_msg_types('std_msgs', False)
+ types2 = roslib.msgs.list_msg_types('std_msgs', True)
+
+ self.assert_('String' in types1, types1)
+ self.assert_('String' in types2, types2)
+ self.assert_('Int32' in types1, types1)
+ self.assert_('Int32' in types2, types2)
+
+ self.assert_('roslib/Header' in types2, types2)
+ self.assert_('roslib/Header' not in types1, types1)
+ self.assert_('roslib/Clock' in types2, types2)
+ self.assert_('roslib/Clock' not in types1, types1)
+ self.assert_('roslib/Log' in types2, types2)
+ self.assert_('roslib/Log' not in types1, types1)
+
+ # std_msgs depends on roslib, so these should be different
+ self.assertNotEquals(types1, types2)
+
+ def test_msg_file(self):
+ f = roslib.msgs.msg_file('roslib', 'Log')
+ self.assert_(os.path.isfile(f))
+ self.assert_(f.endswith('roslib/msg/Log.msg'))
+
+ # msg_file should return paths even for non-existent resources
+ f = roslib.msgs.msg_file('roslib', 'Fake')
+ self.failIf(os.path.isfile(f))
+ self.assert_(f.endswith('roslib/msg/Fake.msg'))
+
+ def test_is_valid_msg_type(self):
+
+ vals = [
+ #basic
+ 'F', 'f', 'Foo', 'Foo1',
+ 'std_msgs/String',
+ # arrays
+ 'Foo[]', 'Foo[1]', 'Foo[10]',
+ ]
+ for v in vals:
+ self.assert_(roslib.msgs.is_valid_msg_type(v), "roslib.msgs.is_valid_msg_type should have returned True for '%s'"%v)
+
+ # bad cases
+ vals = [None, '', '#', '%', 'Foo%', 'Woo Woo',
+ '/', '/String',
+ 'Foo[f]', 'Foo[1d]', 'Foo[-1]', 'Foo[1:10]', 'Foo[', 'Foo]', 'Foo[]Bar']
+ for v in vals:
+ self.failIf(roslib.msgs.is_valid_msg_type(v), "roslib.msgs.is_valid_msg_type should have returned False for '%s'"%v)
+
+ def test_is_valid_constant_type(self):
+ valid = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', \
+ 'uint64', 'float32', 'float64', 'char', 'byte', 'string']
+ invalid = [
+ 'std_msgs/String', '/', 'String',
+ 'time', 'duration','header',
+ ]
+ for v in valid:
+ self.assert_(roslib.msgs.is_valid_constant_type(v), "roslib.msgs.is_valid_constant_type should have returned True for '%s'"%v)
+ for v in invalid:
+ self.failIf(roslib.msgs.is_valid_constant_type(v), "roslib.msgs.is_valid_constant_type should have returned False for '%s'"%v)
+
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_msgspec', MsgSpecTest, coverage_packages=['roslib.msgs'])
+
diff --git a/test/test_roslib/test/test_roslib_names.py b/test/test_roslib/test/test_roslib_names.py
new file mode 100644
index 00000000..b655fd86
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_names.py
@@ -0,0 +1,358 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import sys
+import unittest
+
+import roslib.names
+import rosunit
+
+class NamesTest(unittest.TestCase):
+
+ def test_get_ros_namespace(self):
+ if 'ROS_NAMESPACE' in os.environ:
+ rosns = os.environ['ROS_NAMESPACE']
+ del os.environ['ROS_NAMESPACE']
+ else:
+ rosns = None
+ sysargv = sys.argv
+
+ try:
+ sys.argv = []
+ self.assertEquals('/', roslib.names.get_ros_namespace())
+ self.assertEquals('/', roslib.names.get_ros_namespace(argv=[]))
+ self.assertEquals('/', roslib.names.get_ros_namespace(env={}))
+ self.assertEquals('/', roslib.names.get_ros_namespace(env={}, argv=[]))
+
+ os.environ['ROS_NAMESPACE'] = 'unresolved'
+ self.assertEquals('/unresolved/', roslib.names.get_ros_namespace())
+ self.assertEquals('/unresolved/', roslib.names.get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'}))
+ sys.argv = ['foo', '__ns:=unresolved_override']
+ self.assertEquals('/unresolved_override/', roslib.names.get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'}))
+ self.assertEquals('/override2/', roslib.names.get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'}, argv=['foo', '__ns:=override2']))
+
+ sys.argv = []
+ os.environ['ROS_NAMESPACE'] = '/resolved/'
+ self.assertEquals('/resolved/', roslib.names.get_ros_namespace())
+ self.assertEquals('/resolved/', roslib.names.get_ros_namespace(env={'ROS_NAMESPACE': '/resolved'}))
+
+ del os.environ['ROS_NAMESPACE']
+
+ sys.argv = ['foo', '__ns:=unresolved_ns']
+ self.assertEquals('/unresolved_ns/', roslib.names.get_ros_namespace())
+ self.assertEquals('/unresolved_ns2/', roslib.names.get_ros_namespace(argv=['foo', '__ns:=unresolved_ns2']))
+ sys.argv = ['foo', '__ns:=/resolved_ns/']
+ self.assertEquals('/resolved_ns/', roslib.names.get_ros_namespace())
+ self.assertEquals('/resolved_ns2/', roslib.names.get_ros_namespace(argv=['foo', '__ns:=resolved_ns2']))
+ finally:
+ sys.argv = sysargv
+
+ # restore
+ if rosns:
+ os.environ['ROS_NAMESPACE'] = rosns
+
+ def test_make_global_ns(self):
+ from roslib.names import make_global_ns
+
+ for n in ['~foo']:
+ try:
+ make_global_ns(n)
+ self.fail("make_global_ns should fail on %s"%n)
+ except ValueError: pass
+
+ self.assertEquals('/foo/', make_global_ns('foo'))
+ self.assertEquals('/', make_global_ns(''))
+ self.assertEquals('/foo/', make_global_ns('/foo'))
+ self.assertEquals('/foo/', make_global_ns('/foo/'))
+ self.assertEquals('/foo/bar/', make_global_ns('/foo/bar'))
+ self.assertEquals('/foo/bar/', make_global_ns('/foo/bar/'))
+
+ def test_make_caller_id(self):
+ from roslib.names import make_caller_id
+ if 'ROS_NAMESPACE' is os.environ:
+ rosns = os.environ['ROS_NAMESPACE']
+ del os.environ['ROS_NAMESPACE']
+ else:
+ rosns = None
+
+ for n in ['~name']:
+ try:
+ make_caller_id('~name') # illegal
+ self.fail("make_caller_id should fail on %s"%n)
+ except ValueError: pass
+
+ self.assertEquals('/node/', make_caller_id('node'))
+ self.assertEquals('/bar/node/', make_caller_id('bar/node'))
+ self.assertEquals('/bar/node/', make_caller_id('/bar/node'))
+
+ os.environ['ROS_NAMESPACE'] = '/test/'
+ self.assertEquals('/test/node/', make_caller_id('node'))
+ self.assertEquals('/test/bar/node/', make_caller_id('bar/node'))
+ self.assertEquals('/bar/node/', make_caller_id('/bar/node'))
+
+ # restore
+ if rosns:
+ os.environ['ROS_NAMESPACE'] = rosns
+
+
+ def test_is_global(self):
+ try:
+ roslib.names.is_global(None)
+ self.fail("is_global should raise exception on invalid param")
+ except: pass
+ tests = ['/', '/global', '/global2']
+ for t in tests:
+ self.assert_(roslib.names.is_global(t))
+ fails = ['', 'not_global', 'not/global']
+ for t in fails:
+ self.failIf(roslib.names.is_global(t))
+
+ def test_is_private(self):
+ try:
+ roslib.names.is_private(None)
+ self.fail("is_private should raise exception on invalid param")
+ except: pass
+ tests = ['~name', '~name/sub']
+ for t in tests:
+ self.assert_(roslib.names.is_private(t))
+ fails = ['', 'not_private', 'not/private', 'not/~private', '/not/~private']
+ for t in fails:
+ self.failIf(roslib.names.is_private(t))
+
+ def test_namespace(self):
+ from roslib.names import namespace
+ try:
+ namespace(1)
+ self.fail("1")
+ except TypeError: pass
+ try:
+ namespace(None)
+ self.fail("None")
+ except ValueError: pass
+ self.assertEquals('/', namespace(''))
+ self.assertEquals('/', namespace('/'))
+ self.assertEquals('/', namespace('/foo'))
+ self.assertEquals('/', namespace('/foo/'))
+ self.assertEquals('/foo/', namespace('/foo/bar'))
+ self.assertEquals('/foo/', namespace('/foo/bar/'))
+ self.assertEquals('/foo/bar/', namespace('/foo/bar/baz'))
+ self.assertEquals('/foo/bar/', namespace('/foo/bar/baz/'))
+
+ # unicode tests
+ self.assertEquals(u'/', namespace(u''))
+ self.assertEquals(u'/', namespace(u'/'))
+ self.assertEquals(u'/foo/bar/', namespace(u'/foo/bar/baz/'))
+
+ def test_nsjoin(self):
+ from roslib.names import ns_join
+
+ # private and global names cannot be joined
+ self.assertEquals('~name', ns_join('/foo', '~name'))
+ self.assertEquals('/name', ns_join('/foo', '/name'))
+ self.assertEquals('~name', ns_join('~', '~name'))
+ self.assertEquals('/name', ns_join('/', '/name'))
+
+ # ns can be '~' or '/'
+ self.assertEquals('~name', ns_join('~', 'name'))
+ self.assertEquals('/name', ns_join('/', 'name'))
+
+ self.assertEquals('/ns/name', ns_join('/ns', 'name'))
+ self.assertEquals('/ns/name', ns_join('/ns/', 'name'))
+ self.assertEquals('/ns/ns2/name', ns_join('/ns', 'ns2/name'))
+ self.assertEquals('/ns/ns2/name', ns_join('/ns/', 'ns2/name'))
+
+ # allow ns to be empty
+ self.assertEquals('name', ns_join('', 'name'))
+
+
+ def test_load_mappings(self):
+ from roslib.names import load_mappings
+ self.assertEquals({}, load_mappings([]))
+ self.assertEquals({}, load_mappings(['foo']))
+ self.assertEquals({}, load_mappings([':=']))
+ self.assertEquals({}, load_mappings([':=:=']))
+ self.assertEquals({}, load_mappings(['f:=']))
+ self.assertEquals({}, load_mappings([':=b']))
+ self.assertEquals({}, load_mappings(['foo:=bar:=baz']))
+ # should ignore node param assignments
+ self.assertEquals({}, load_mappings(['_foo:=bar']))
+
+ self.assertEquals({'foo': 'bar'}, load_mappings(['foo:=bar']))
+ # should allow double-underscore names
+ self.assertEquals({'__foo': 'bar'}, load_mappings(['__foo:=bar']))
+ self.assertEquals({'foo': 'bar'}, load_mappings(['./f', '-x', '--blah', 'foo:=bar']))
+ self.assertEquals({'a': '1', 'b': '2', 'c': '3'}, load_mappings(['c:=3', 'c:=', ':=3', 'a:=1', 'b:=2']))
+
+ def test_resource_name(self):
+ from roslib.names import resource_name
+ self.assertEquals('foo/bar', resource_name('foo', 'bar'))
+ self.assertEquals('bar', resource_name('foo', 'bar', my_pkg='foo'))
+ self.assertEquals('foo/bar', resource_name('foo', 'bar', my_pkg='bar'))
+ self.assertEquals('foo/bar', resource_name('foo', 'bar', my_pkg=''))
+ self.assertEquals('foo/bar', resource_name('foo', 'bar', my_pkg=None))
+
+ def test_resource_name_base(self):
+ from roslib.names import resource_name_base
+ self.assertEquals('', resource_name_base(''))
+ self.assertEquals('bar', resource_name_base('bar'))
+ self.assertEquals('bar', resource_name_base('foo/bar'))
+ self.assertEquals('bar', resource_name_base('/bar'))
+ self.assertEquals('', resource_name_base('foo/'))
+
+ def test_resource_name_package(self):
+ from roslib.names import resource_name_package
+ self.assertEquals(None, resource_name_package(''))
+ self.assertEquals(None, resource_name_package('foo'))
+ self.assertEquals('foo', resource_name_package('foo/'))
+ self.assertEquals('foo', resource_name_package('foo/bar'))
+
+ def test_package_resource_name(self):
+ from roslib.names import package_resource_name
+ self.assertEquals(('', ''), package_resource_name(''))
+ self.assertEquals(('', 'foo'), package_resource_name('foo'))
+ self.assertEquals(('foo', 'bar'), package_resource_name('foo/bar'))
+ self.assertEquals(('foo', ''), package_resource_name('foo/'))
+ try:
+ # only allowed single separator
+ package_resource_name("foo/bar/baz")
+ self.fail("should have raised ValueError")
+ except ValueError:
+ pass
+
+
+ def test_is_legal_resource_name(self):
+ from roslib.names import is_legal_resource_name
+ failures = [None, '', 'hello\n', '\t', 'foo++', 'foo-bar', '#foo',
+ ' name', 'name ',
+ '~name', '/name',
+ '1name', 'foo\\']
+ for f in failures:
+ self.failIf(is_legal_resource_name(f), f)
+ tests = ['f', 'f1', 'f_', 'foo', 'foo_bar', 'foo/bar', 'roslib/Log']
+ for t in tests:
+ self.assert_(is_legal_resource_name(t), t)
+
+ def test_is_legal_name(self):
+ from roslib.names import is_legal_name
+ failures = [None,
+ 'foo++', 'foo-bar', '#foo',
+ 'hello\n', '\t', ' name', 'name ',
+ 'f//b',
+ '1name', 'foo\\']
+ for f in failures:
+ self.failIf(is_legal_name(f), f)
+ tests = ['',
+ 'f', 'f1', 'f_', 'f/', 'foo', 'foo_bar', 'foo/bar', 'foo/bar/baz',
+ '~f', '~a/b/c',
+ '~/f',
+ '/a/b/c/d', '/']
+ for t in tests:
+ self.assert_(is_legal_name(t), "[%s]"%t)
+
+ def test_is_legal_base_name(self):
+ from roslib.names import is_legal_base_name
+ failures = [None, '', 'hello\n', '\t', 'foo++', 'foo-bar', '#foo',
+ 'f/', 'foo/bar', '/', '/a',
+ 'f//b',
+ '~f', '~a/b/c',
+ ' name', 'name ',
+ '1name', 'foo\\']
+ for f in failures:
+ self.failIf(is_legal_base_name(f), f)
+ tests = ['f', 'f1', 'f_', 'foo', 'foo_bar']
+ for t in tests:
+ self.assert_(is_legal_base_name(t), "[%s]"%t)
+
+ def test_is_legal_resource_base_name(self):
+ from roslib.names import is_legal_resource_base_name
+ failures = [None, '', 'hello\n', '\t', 'foo++', 'foo-bar', '#foo',
+ 'f/', 'foo/bar', '/', '/a',
+ 'f//b',
+ '~f', '~a/b/c',
+ '~/f',
+ ' name', 'name ',
+ '1name', 'foo\\']
+ for f in failures:
+ self.failIf(is_legal_resource_base_name(f), f)
+ tests = ['f', 'f1', 'f_', 'foo', 'foo_bar']
+ for t in tests:
+ self.assert_(is_legal_resource_base_name(t), "[%s]"%t)
+
+ def test_resolve_name(self):
+ from roslib.names import resolve_name
+ # TODO: test with remappings
+ tests = [
+ ('', '/', '/'),
+ ('', '/node', '/'),
+ ('', '/ns1/node', '/ns1/'),
+
+ ('foo', '', '/foo'),
+ ('foo/', '', '/foo'),
+ ('/foo', '', '/foo'),
+ ('/foo/', '', '/foo'),
+ ('/foo', '/', '/foo'),
+ ('/foo/', '/', '/foo'),
+ ('/foo', '/bar', '/foo'),
+ ('/foo/', '/bar', '/foo'),
+
+ ('foo', '/ns1/ns2', '/ns1/foo'),
+ ('foo', '/ns1/ns2/', '/ns1/foo'),
+ ('foo', '/ns1/ns2/ns3/', '/ns1/ns2/foo'),
+ ('foo/', '/ns1/ns2', '/ns1/foo'),
+ ('/foo', '/ns1/ns2', '/foo'),
+ ('foo/bar', '/ns1/ns2', '/ns1/foo/bar'),
+ ('foo//bar', '/ns1/ns2', '/ns1/foo/bar'),
+ ('foo/bar', '/ns1/ns2/ns3', '/ns1/ns2/foo/bar'),
+ ('foo//bar//', '/ns1/ns2/ns3', '/ns1/ns2/foo/bar'),
+
+ ('~foo', '/', '/foo'),
+ ('~foo', '/node', '/node/foo'),
+ ('~foo', '/ns1/ns2', '/ns1/ns2/foo'),
+ ('~foo/', '/ns1/ns2', '/ns1/ns2/foo'),
+ ('~foo/bar', '/ns1/ns2', '/ns1/ns2/foo/bar'),
+
+ # #3044
+ ('~/foo', '/', '/foo'),
+ ('~/foo', '/node', '/node/foo'),
+ ('~/foo', '/ns1/ns2', '/ns1/ns2/foo'),
+ ('~/foo/', '/ns1/ns2', '/ns1/ns2/foo'),
+ ('~/foo/bar', '/ns1/ns2', '/ns1/ns2/foo/bar'),
+
+ ]
+ for name, node_name, v in tests:
+ self.assertEquals(v, resolve_name(name, node_name))
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_names', NamesTest, coverage_packages=['roslib.names'])
+
diff --git a/test/test_roslib/test/test_roslib_network.py b/test/test_roslib/test/test_roslib_network.py
new file mode 100644
index 00000000..01d2f373
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_network.py
@@ -0,0 +1,247 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import struct
+import sys
+import unittest
+
+import roslib.network
+import rosunit
+
+class MockSock(object):
+ def __init__(self, data=''):
+ self.data = data
+ def recv(self):
+ d = self.data
+ self.data = ''
+ return d
+ def sendall(self, d):
+ self.data = self.data + d
+ def send(self, d):
+ self.data = self.data + d
+ return len(d)
+
+
+class NetworkTest(unittest.TestCase):
+
+ def test_encode_ros_handshake_header(self):
+ from roslib.network import encode_ros_handshake_header
+ d = {}
+ self.assertEquals(struct.pack('= TVal())
+ self.assert_(v <= TVal())
+ self.assert_(v < TVal(0,1))
+ self.assert_(TVal(0,1) > v)
+ v.set(0, 0)
+ self.assertEquals(0, v.secs)
+ self.assertEquals(0, v.nsecs)
+ v.set(1, 0)
+ self.assertEquals(1, v.secs)
+ self.assertEquals(0, v.nsecs)
+ v.set(0, 1)
+ self.assertEquals(0, v.secs)
+ self.assertEquals(1, v.nsecs)
+ # - set does _not_ canonicalize
+ v.set(0, 1000000000)
+ self.assertEquals(0, v.secs)
+ self.assertEquals(1000000000, v.nsecs)
+ v.canon()
+ self.assertEquals(1, v.secs)
+ self.assertEquals(0, v.nsecs)
+
+ # - test seconds
+ v = TVal(1)
+ self.assertEquals(1, v.secs)
+ self.assertEquals(0, v.nsecs)
+ self.assert_(v) # test __zero__
+ self.failIf(v.is_zero())
+ self.assertEquals('1000000000', str(v))
+ self.assertEquals(1000000000, v.to_nsec())
+ self.assertEquals(v, v)
+ self.assertEquals(v, TVal(1))
+ self.assertEquals(v, TVal(1, 0))
+ self.assertEquals(v, TVal(0,1000000000))
+ self.assertEquals(v.__hash__(), TVal(0,1000000000).__hash__())
+ self.assertNotEquals(v, TVal(0, 0))
+ self.assertNotEquals(v.__hash__(), TVal(0, 0).__hash__())
+ self.assertEquals(NotImplemented, v.__ge__(0))
+ class Foo(object): pass
+ self.assertEquals(NotImplemented, v.__gt__(Foo()))
+ self.assertEquals(NotImplemented, v.__ge__(Foo()))
+ self.assertEquals(NotImplemented, v.__le__(Foo()))
+ self.assertEquals(NotImplemented, v.__lt__(Foo()))
+ self.failIf(v.__eq__(Foo()))
+ self.assert_(v.__ne__(Foo()))
+ self.assert_(v >= TVal())
+ self.assert_(v <= TVal(1))
+ self.assert_(v <= TVal(1,0))
+ self.assert_(v <= TVal(2,0))
+ self.assert_(v < TVal(2))
+ self.assert_(v < TVal(1,1))
+ self.assert_(TVal(1,1) > v)
+ self.assert_(TVal(2) > v)
+ # - test ns
+ v = TVal(0, 1)
+ self.assertEquals(0, v.secs)
+ self.assertEquals(1, v.nsecs)
+ self.assert_(v) # test __zero__
+ self.failIf(v.is_zero())
+ self.assertEquals('1', str(v))
+ self.assertEquals(1, v.to_nsec())
+ self.assertEquals(v, v)
+ self.assertEquals(v, TVal(0,1))
+ self.assertNotEquals(v, TVal(0, 0))
+ self.assert_(v >= TVal())
+ self.assert_(v <= TVal(1))
+ self.assert_(v <= TVal(0,1))
+ self.assert_(v <= TVal(2,0))
+ self.assert_(v < TVal(0,2))
+ self.assert_(v < TVal(1))
+ self.assert_(TVal(1) > v)
+ self.assert_(TVal(0,2) > v)
+ # - test canon
+ v = TVal(1, 1000000000)
+ self.assertEquals(2, v.secs)
+ self.assertEquals(0, v.nsecs)
+ self.assertEquals(2, v.to_sec())
+ self.assertEquals(2000000000, v.to_nsec())
+
+ v = TVal(1, 1000000001)
+ self.assertEquals(2, v.secs)
+ self.assertEquals(1, v.nsecs)
+ self.assertEquals(2.000000001, v.to_sec())
+ self.assertEquals(2000000001, v.to_nsec())
+
+ v = TVal(1, -1000000000)
+ self.assertEquals(0, v.secs)
+ self.assertEquals(0, v.nsecs)
+ v = TVal(1, -999999999)
+ self.assertEquals(0, v.secs)
+ self.assertEquals(1, v.nsecs)
+ self.assertEquals(0.000000001, v.to_sec())
+ self.assertEquals(1, v.to_nsec())
+
+ if test_neg:
+ v = TVal(-1, -1000000000)
+ self.assertEquals(-2, v.secs)
+ self.assertEquals(0, v.nsecs)
+ self.assertEquals(-2, v.to_sec())
+ self.assertEquals(-2000000000, v.to_nsec())
+
+ v = TVal(-2, 1000000000)
+ self.assertEquals(-1, v.secs)
+ self.assertEquals(0, v.nsecs)
+ self.assertEquals(-1, v.to_sec())
+ self.assertEquals(-1000000000, v.to_nsec())
+
+
+ # test some more hashes
+ self.assertEquals(TVal(1).__hash__(), TVal(1).__hash__())
+ self.assertEquals(TVal(1,1).__hash__(), TVal(1,1).__hash__())
+ self.assertNotEquals(TVal(1).__hash__(), TVal(2).__hash__())
+ self.assertNotEquals(TVal(1,1).__hash__(), TVal(1,2).__hash__())
+ self.assertNotEquals(TVal(1,1).__hash__(), TVal(2,1).__hash__())
+
+ def test_Time(self):
+ Time = roslib.rostime.Time
+ Duration = roslib.rostime.Duration
+ self.test_TVal(TVal=Time, test_neg=False)
+
+ # #1600 Duration > Time should fail
+ failed = False
+ try:
+ v = Duration.from_sec(0.1) > Time.from_sec(0.5)
+ failed = True
+ except: pass
+ self.failIf(failed, "should have failed to compare")
+ try:
+ v = Time.from_sec(0.4) > Duration.from_sec(0.1)
+ failed = True
+ except: pass
+ self.failIf(failed, "should have failed to compare")
+
+ # TODO: sub
+
+ # neg time fails
+ try:
+ Time(-1)
+ failed = True
+ except: pass
+ self.failIf(failed, "negative time not allowed")
+ try:
+ Time(1, -1000000001)
+ failed = True
+ except: pass
+ self.failIf(failed, "negative time not allowed")
+
+ # test Time.now() is within 10 seconds of actual time (really generous)
+ import time
+ t = time.time()
+ v = Time.from_sec(t)
+ self.assertEquals(v.to_sec(), t)
+ # test from_sec()
+ self.assertEquals(Time.from_sec(0), Time())
+ self.assertEquals(Time.from_sec(1.), Time(1))
+ self.assertEquals(Time.from_sec(v.to_sec()), v)
+ self.assertEquals(v.from_sec(v.to_sec()), v)
+ # test to_time()
+ self.assertEquals(v.to_sec(), v.to_time())
+
+ # test addition
+ # - time + time fails
+ try:
+ v = Time(1,0) + Time(1, 0)
+ failed = True
+ except: pass
+ self.failIf(failed, "Time + Time must fail")
+
+ # - time + duration
+ v = Time(1,0) + Duration(1, 0)
+ self.assertEquals(Time(2, 0), v)
+ v = Duration(1, 0) + Time(1,0)
+ self.assertEquals(Time(2, 0), v)
+ v = Time(1,1) + Duration(1, 1)
+ self.assertEquals(Time(2, 2), v)
+ v = Duration(1, 1) + Time(1,1)
+ self.assertEquals(Time(2, 2), v)
+
+ v = Time(1) + Duration(0, 1000000000)
+ self.assertEquals(Time(2), v)
+ v = Duration(1) + Time(0, 1000000000)
+ self.assertEquals(Time(2), v)
+
+ v = Time(100, 100) + Duration(300)
+ self.assertEquals(Time(400, 100), v)
+ v = Duration(300) + Time(100, 100)
+ self.assertEquals(Time(400, 100), v)
+
+ v = Time(100, 100) + Duration(300, 300)
+ self.assertEquals(Time(400, 400), v)
+ v = Duration(300, 300) + Time(100, 100)
+ self.assertEquals(Time(400, 400), v)
+
+ v = Time(100, 100) + Duration(300, -101)
+ self.assertEquals(Time(399, 999999999), v)
+ v = Duration(300, -101) + Time(100, 100)
+ self.assertEquals(Time(399, 999999999), v)
+
+ # test subtraction
+ try:
+ v = Time(1,0) - 1
+ failed = True
+ except: pass
+ self.failIf(failed, "Time - non Duration must fail")
+ class Foob(object): pass
+ try:
+ v = Time(1,0) - Foob()
+ failed = True
+ except: pass
+ self.failIf(failed, "Time - non TVal must fail")
+
+ # - Time - Duration
+ v = Time(1,0) - Duration(1, 0)
+ self.assertEquals(Time(), v)
+
+ v = Time(1,1) - Duration(-1, -1)
+ self.assertEquals(Time(2, 2), v)
+ v = Time(1) - Duration(0, 1000000000)
+ self.assertEquals(Time(), v)
+ v = Time(2) - Duration(0, 1000000000)
+ self.assertEquals(Time(1), v)
+ v = Time(400, 100) - Duration(300)
+ self.assertEquals(Time(100, 100), v)
+ v = Time(100, 100) - Duration(0, 101)
+ self.assertEquals(Time(99, 999999999), v)
+
+ # - Time - Time = Duration
+ v = Time(100, 100) - Time(100, 100)
+ self.assertEquals(Duration(), v)
+ v = Time(100, 100) - Time(100)
+ self.assertEquals(Duration(0,100), v)
+ v = Time(100) - Time(200)
+ self.assertEquals(Duration(-100), v)
+
+ # Time (float secs) vs. Time(int, int)
+ self.assertEquals(Time.from_sec(0.5), Time(0.5))
+ t = Time(0.5)
+ self.assert_(type(t.secs) == int)
+ self.assertEquals(0, t.secs)
+ self.assertEquals(500000000, t.nsecs)
+
+ try:
+ Time(0.5, 0.5)
+ self.fail("should have thrown value error")
+ except ValueError: pass
+
+ def test_Duration(self):
+ Duration = roslib.rostime.Duration
+ self.test_TVal(TVal=Duration, test_neg=True)
+
+ # test from_sec
+ v = Duration(1000)
+ self.assertEquals(v, Duration.from_sec(v.to_sec()))
+ self.assertEquals(v, v.from_sec(v.to_sec()))
+ v = Duration(0,1000)
+ self.assertEquals(v, Duration.from_sec(v.to_sec()))
+ self.assertEquals(v, v.from_sec(v.to_sec()))
+
+ # test neg
+ v = -Duration(1, -1)
+ self.assertEquals(-1, v.secs)
+ self.assertEquals(1, v.nsecs)
+ v = -Duration(-1, -1)
+ self.assertEquals(1, v.secs)
+ self.assertEquals(1, v.nsecs)
+ v = -Duration(-1, 1)
+ self.assertEquals(0, v.secs)
+ self.assertEquals(999999999, v.nsecs)
+
+ # test addition
+ failed = False
+ try:
+ v = Duration(1,0) + Time(1, 0)
+ failed = True
+ except: pass
+ self.failIf(failed, "Duration + Time must fail")
+ try:
+ v = Duration(1,0) + 1
+ failed = True
+ except: pass
+ self.failIf(failed, "Duration + int must fail")
+
+ v = Duration(1,0) + Duration(1, 0)
+ self.assertEquals(2, v.secs)
+ self.assertEquals(0, v.nsecs)
+ self.assertEquals(Duration(2, 0), v)
+ v = Duration(-1,-1) + Duration(1, 1)
+ self.assertEquals(0, v.secs)
+ self.assertEquals(0, v.nsecs)
+ self.assertEquals(Duration(), v)
+ v = Duration(1) + Duration(0, 1000000000)
+ self.assertEquals(2, v.secs)
+ self.assertEquals(0, v.nsecs)
+ self.assertEquals(Duration(2), v)
+ v = Duration(100, 100) + Duration(300)
+ self.assertEquals(Duration(400, 100), v)
+ v = Duration(100, 100) + Duration(300, 300)
+ self.assertEquals(Duration(400, 400), v)
+ v = Duration(100, 100) + Duration(300, -101)
+ self.assertEquals(Duration(399, 999999999), v)
+
+ # test subtraction
+ try:
+ v = Duration(1,0) - 1
+ failed = True
+ except: pass
+ self.failIf(failed, "Duration - non duration must fail")
+ try:
+ v = Duration(1, 0) - Time(1,0)
+ failed = True
+ except: pass
+ self.failIf(failed, "Duration - Time must fail")
+
+ v = Duration(1,0) - Duration(1, 0)
+ self.assertEquals(Duration(), v)
+ v = Duration(-1,-1) - Duration(1, 1)
+ self.assertEquals(Duration(-3, 999999998), v)
+ v = Duration(1) - Duration(0, 1000000000)
+ self.assertEquals(Duration(), v)
+ v = Duration(2) - Duration(0, 1000000000)
+ self.assertEquals(Duration(1), v)
+ v = Duration(100, 100) - Duration(300)
+ self.assertEquals(Duration(-200, 100), v)
+ v = Duration(100, 100) - Duration(300, 101)
+ self.assertEquals(Duration(-201, 999999999), v)
+
+ # test abs
+ self.assertEquals(abs(Duration()), Duration())
+ self.assertEquals(abs(Duration(1)), Duration(1))
+ self.assertEquals(abs(Duration(-1)), Duration(1))
+ self.assertEquals(abs(Duration(0,-1)), Duration(0,1))
+ self.assertEquals(abs(Duration(-1,-1)), Duration(1,1))
+
+ # Duration (float secs) vs. Duration(int, int)
+ self.assertEquals(Duration.from_sec(0.5), Duration(0.5))
+ t = Duration(0.5)
+ self.assert_(type(t.secs) == int)
+ self.assertEquals(0, t.secs)
+ self.assertEquals(500000000, t.nsecs)
+
+ try:
+ Duration(0.5, 0.5)
+ self.fail("should have thrown value error")
+ except ValueError: pass
+
+ # Test mul
+ self.assertEquals(Duration(4), Duration(2) * 2)
+ self.assertEquals(Duration(4), Duration(2) * 2.)
+ self.assertEquals(Duration(10), Duration(4) * 2.5)
+ self.assertEquals(Duration(4, 8), Duration(2, 4) * 2)
+ v = Duration(4, 8) - (Duration(2, 4) * 2.)
+ self.assert_(abs(v.to_nsec()) < 100)
+ v = Duration(5, 10) - (Duration(2, 4) * 2.5)
+ self.assert_(abs(v.to_nsec()) < 100)
+
+ # Test div
+ self.assertEquals(Duration(4), Duration(8) / 2)
+ self.assertEquals(Duration(4), Duration(8) / 2.)
+ self.assertEquals(Duration(4), Duration(8) // 2)
+ self.assertEquals(Duration(4), Duration(8) // 2.)
+ self.assertEquals(Duration(4), Duration(9) // 2)
+ self.assertEquals(Duration(4), Duration(9) // 2.)
+ self.assertEquals(Duration(4, 2), Duration(8, 4) / 2)
+ v = Duration(4, 2) - (Duration(8, 4) / 2.)
+ self.assert_(abs(v.to_nsec()) < 100)
+
+ self.assertEquals(Duration(4, 2), Duration(8, 4) // 2)
+ self.assertEquals(Duration(4, 2), Duration(9, 5) // 2)
+ v = Duration(4, 2) - (Duration(9, 5) // 2.)
+ self.assert_(abs(v.to_nsec()) < 100)
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_rostime', RostimeTest, coverage_packages=['roslib.rostime'])
+
diff --git a/test/test_roslib/test/test_roslib_scriptutil.py b/test/test_roslib/test/test_roslib_scriptutil.py
new file mode 100644
index 00000000..1fbfd52d
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_scriptutil.py
@@ -0,0 +1,67 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import struct
+import sys
+import unittest
+
+import rosunit
+
+class RoslibScriptutilTest(unittest.TestCase):
+
+ def test_myargv(self):
+ orig_argv = sys.argv
+ try:
+ from roslib.scriptutil import myargv
+ args = myargv()
+ sysargv = [a for a in sys.argv if not a.startswith('__log:=')]
+ self.assertEquals(args, sysargv)
+ self.assertEquals(['foo', 'bar', 'baz'], myargv(['foo','bar', 'baz']))
+ self.assertEquals(['-foo', 'bar', '-baz'], myargv(['-foo','bar', '-baz']))
+
+ self.assertEquals(['foo'], myargv(['foo','bar:=baz']))
+ self.assertEquals(['foo'], myargv(['foo','-bar:=baz']))
+ finally:
+ sys.argv = orig_argv
+
+ def test_interactive(self):
+ import roslib.scriptutil
+ self.failIf(roslib.scriptutil.is_interactive(), "interactive should be false by default")
+ for v in [True, False]:
+ roslib.scriptutil.set_interactive(v)
+ self.assertEquals(v, roslib.scriptutil.is_interactive())
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_scriptutil', RoslibScriptutilTest, coverage_packages=['roslib.scriptutil'])
+
diff --git a/test/test_roslib/test/test_roslib_stacks.py b/test/test_roslib/test/test_roslib_stacks.py
new file mode 100644
index 00000000..4bd4ac88
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_stacks.py
@@ -0,0 +1,200 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import struct
+import sys
+import unittest
+
+import roslib.rosenv
+import roslib.stacks
+import rosunit
+
+class RoslibStacksTest(unittest.TestCase):
+
+ def test_packages_of(self):
+ from roslib.stacks import packages_of
+ pkgs = packages_of('ros_comm')
+ for p in ['test_roslib', 'rospy', 'roscpp']:
+ self.assert_(p in pkgs)
+ # due to caching behavior, test twice
+ pkgs = packages_of('ros_comm')
+ for p in ['test_roslib', 'rospy', 'roscpp']:
+ self.assert_(p in pkgs)
+
+ try:
+ packages_of(None)
+ self.fail("should have raised ValueError")
+ except ValueError: pass
+
+ def test_stack_of(self):
+ import roslib.packages
+ from roslib.stacks import stack_of
+ self.assertEquals('ros_comm', stack_of('test_roslib'))
+ # due to caching, test twice
+ self.assertEquals('ros_comm', stack_of('test_roslib'))
+ try:
+ stack_of('fake_test_roslib')
+ self.fail("should have failed")
+ except roslib.packages.InvalidROSPkgException:
+ pass
+
+ def test_list_stacks(self):
+ from roslib.stacks import list_stacks
+ l = list_stacks()
+ self.assert_('ros_comm' in l)
+
+ # make sure it is equivalent to rosstack list
+ from roslib.rospack import rosstackexec
+ l2 = [x for x in rosstackexec(['list']).split('\n') if x]
+ l2 = [x.split()[0] for x in l2]
+ self.assertEquals(set(l), set(l2), set(l) ^ set(l2))
+
+ def test_list_stacks_by_path(self):
+ from roslib.stacks import list_stacks_by_path
+
+ # test with the ros stack
+ rr = roslib.rosenv.get_ros_root()
+ self.assertEquals(['ros'], list_stacks_by_path(rr))
+ stacks = []
+ self.assertEquals(['ros'], list_stacks_by_path(rr, stacks))
+ self.assertEquals(['ros'], stacks)
+ self.assertEquals(['ros'], list_stacks_by_path(rr, stacks))
+
+ stacks.extend(['fake_stack', 'fake_stack2'])
+ self.assertEquals(['ros', 'fake_stack', 'fake_stack2'], list_stacks_by_path(rr, stacks))
+
+ cache = {}
+ self.assertEquals(['ros'], list_stacks_by_path(rr, cache=cache))
+ self.assertEquals({'ros': rr}, cache)
+
+ # test with synthetic stacks
+ test_dir = os.path.join(roslib.packages.get_pkg_dir('test_roslib'), 'test', 'stack_tests')
+ self.assertEquals(set(['bar', 'foo']), set(list_stacks_by_path(test_dir)))
+
+ test_dir = os.path.join(roslib.packages.get_pkg_dir('test_roslib'), 'test', 'stack_tests', 's1')
+ self.assertEquals(set(['bar', 'foo']), set(list_stacks_by_path(test_dir)))
+
+ test_dir = os.path.join(roslib.packages.get_pkg_dir('test_roslib'), 'test', 'stack_tests', 's1', 'bar')
+ self.assertEquals(['bar'], list_stacks_by_path(test_dir))
+
+ # test symlink following
+
+ test_dir = os.path.join(roslib.packages.get_pkg_dir('test_roslib'), 'test', 'stack_tests2')
+ self.assertEquals(set(['foo', 'bar']), set(list_stacks_by_path(test_dir)))
+
+ def test_get_stack_dir(self):
+ import roslib.rosenv
+ import roslib.packages
+ from roslib.stacks import get_stack_dir, InvalidROSStackException, list_stacks
+ self.assertEquals(roslib.rosenv.get_ros_root(), get_stack_dir('ros'))
+ try:
+ get_stack_dir('non_existent')
+ self.fail("should have raised")
+ except roslib.stacks.InvalidROSStackException:
+ pass
+
+ # make sure it agrees with rosstack
+ stacks = list_stacks()
+ from roslib.rospack import rosstackexec
+ for s in stacks:
+ self.assertEquals(get_stack_dir(s), rosstackexec(['find', s]))
+
+ # now manipulate the environment to test precedence
+ # - save original RPP as we popen rosstack in other tests
+ rpp = os.environ.get(roslib.rosenv.ROS_PACKAGE_PATH, None)
+ try:
+ d = roslib.packages.get_pkg_dir('test_roslib')
+ d = os.path.join(d, 'test', 'stack_tests')
+
+ # - s1/s2/s3
+ print "s1/s2/s3"
+ paths = [os.path.join(d, p) for p in ['s1', 's2', 's3']]
+ os.environ[roslib.rosenv.ROS_PACKAGE_PATH] = os.pathsep.join(paths)
+ # - run multiple times to test caching
+ for i in xrange(2):
+ stacks = roslib.stacks.list_stacks()
+ self.assert_('foo' in stacks)
+ self.assert_('bar' in stacks)
+
+ foo_p = os.path.join(d, 's1', 'foo')
+ bar_p = os.path.join(d, 's1', 'bar')
+ self.assertEquals(foo_p, roslib.stacks.get_stack_dir('foo'))
+ self.assertEquals(bar_p, roslib.stacks.get_stack_dir('bar'))
+
+ # - s2/s3/s1
+ print "s2/s3/s1"
+
+ paths = [os.path.join(d, p) for p in ['s2', 's3', 's1']]
+ os.environ[roslib.rosenv.ROS_PACKAGE_PATH] = os.pathsep.join(paths)
+ stacks = roslib.stacks.list_stacks()
+ self.assert_('foo' in stacks)
+ self.assert_('bar' in stacks)
+
+ foo_p = os.path.join(d, 's2', 'foo')
+ bar_p = os.path.join(d, 's1', 'bar')
+ self.assertEquals(foo_p, roslib.stacks.get_stack_dir('foo'))
+ self.assertEquals(bar_p, roslib.stacks.get_stack_dir('bar'))
+ finally:
+ #restore rpp
+ if rpp is not None:
+ os.environ[roslib.rosenv.ROS_PACKAGE_PATH] = rpp
+ else:
+ del os.environ[roslib.rosenv.ROS_PACKAGE_PATH]
+
+ def test_expand_to_packages(self):
+ from roslib.stacks import expand_to_packages
+ try:
+ # it's possible to accidentally pass in a sequence type
+ # like a string and get weird results, so check that we
+ # don't
+ self.assertEquals(([], []), expand_to_packages('ros_comm'))
+ self.fail("expand_to_packages should only take in a list of strings")
+ except ValueError: pass
+
+ self.assertEquals(([], []), expand_to_packages([]))
+ self.assertEquals((['rospy', 'test_roslib', 'roslib'], []), expand_to_packages(['rospy', 'test_roslib', 'roslib']))
+ self.assertEquals(([], ['bogus_one', 'bogus_two']), expand_to_packages(['bogus_one', 'bogus_two']))
+
+ self.assertEquals(([], ['bogus_one', 'bogus_two']), expand_to_packages(['bogus_one', 'bogus_two']))
+
+ # TODO: setup directory tree so that this can be more precisely calculated
+ valid, invalid = expand_to_packages(['ros_comm', 'bogus_one'])
+ self.assertEquals(['bogus_one'], invalid)
+ check = ['rospy', 'roscpp', 'rostest', 'std_msgs']
+ for c in check:
+ self.assert_(c in valid, "expected [%s] to be in ros expansion"%c)
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_stacks', RoslibStacksTest, coverage_packages=['roslib.stacks'])
+
diff --git a/test/test_roslib/test/test_roslib_substitution_args.py b/test/test_roslib/test/test_roslib_substitution_args.py
new file mode 100644
index 00000000..a13db5da
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_substitution_args.py
@@ -0,0 +1,170 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import sys
+import unittest
+
+import rosunit
+
+class SubArgsTest(unittest.TestCase):
+
+ def test__arg(self):
+ import random
+ from roslib.substitution_args import _arg, ArgException, SubstitutionException
+
+ ctx = { 'arg': {
+ 'foo': '12345',
+ 'bar': 'hello world',
+ 'baz': 'sim',
+ 'empty': '',
+ }
+ }
+
+ # test invalid
+ try:
+ _arg('$(arg)', 'arg', [], ctx)
+ self.fail("should have thrown")
+ except SubstitutionException:
+ pass
+
+ # test normal
+ tests = [
+ ('12345', ('$(arg foo)', 'arg foo', ['foo'], ctx)),
+ ('', ('$(arg empty)', 'arg empty', ['empty'], ctx)),
+ ('sim', ('$(arg baz)', 'arg baz', ['baz'], ctx)),
+
+ # test with other args present, should only resolve match
+ ('1234512345', ('$(arg foo)$(arg foo)', 'arg foo', ['foo'], ctx)),
+ ('12345$(arg baz)', ('$(arg foo)$(arg baz)', 'arg foo', ['foo'], ctx)),
+ ('$(arg foo)sim', ('$(arg foo)$(arg baz)', 'arg baz', ['baz'], ctx)),
+
+ # test double-resolve safe
+ ('12345', ('12345', 'arg foo', ['foo'], ctx)),
+ ]
+
+ for result, test in tests:
+ resolved, a, args, context = test
+ self.assertEquals(result, _arg(resolved, a, args, context))
+
+ # - test that all fail if ctx is not set
+ for result, test in tests:
+ resolved, a, args, context = test
+ try:
+ _arg(resolved, a, args, {})
+ self.fail("should have thrown")
+ except ArgException, e:
+ self.assertEquals(args[0], str(e))
+ try:
+ _arg(resolved, a, args, {'arg': {}})
+ self.fail("should have thrown")
+ except ArgException, e:
+ self.assertEquals(args[0], str(e))
+
+
+ def test_resolve_args(self):
+ from roslib.substitution_args import resolve_args, SubstitutionException
+ from roslib.packages import get_pkg_dir
+ rospy_dir = get_pkg_dir('rospy', required=True)
+
+ anon_context = {'foo': 'bar'}
+ arg_context = {'fuga': 'hoge', 'car': 'cdr'}
+ context = {'anon': anon_context, 'arg': arg_context }
+
+ tests = [
+ ('$(find rospy)', rospy_dir),
+ ('hello$(find rospy)', 'hello'+rospy_dir),
+ ('$(find rospy )', rospy_dir),
+ ('$$(find rospy )', '$'+rospy_dir),
+ ('$( find rospy )', rospy_dir),
+ ('$(find rospy )', rospy_dir),
+ ('$(find rospy)$(find rospy)', rospy_dir+rospy_dir),
+ ('$(find rospy)/foo/bar.xml', rospy_dir+os.sep+'foo'+os.sep+'bar.xml'),
+ (r'$(find rospy)\foo\bar.xml $(find rospy)\bar.xml', rospy_dir+os.sep+'foo'+os.sep+'bar.xml '+rospy_dir+os.sep+'bar.xml'),
+ ('$(find rospy)\\foo\\bar.xml more/stuff\\here', rospy_dir+os.sep+'foo'+os.sep+'bar.xml more/stuff\\here'),
+ ('$(env ROS_ROOT)', os.environ['ROS_ROOT']),
+ ('$(env ROS_ROOT)', os.environ['ROS_ROOT']),
+ ('$(env ROS_ROOT )', os.environ['ROS_ROOT']),
+ ('$(optenv ROS_ROOT)', os.environ['ROS_ROOT']),
+ ('$(optenv ROS_ROOT)$(optenv ROS_ROOT)', os.environ['ROS_ROOT']+os.environ['ROS_ROOT']),
+ ('$(optenv ROS_ROOT alternate text)', os.environ['ROS_ROOT']),
+ ('$(optenv NOT_ROS_ROOT)', ''),
+ ('$(optenv NOT_ROS_ROOT)more stuff', 'more stuff'),
+ ('$(optenv NOT_ROS_ROOT alternate)', 'alternate'),
+ ('$(optenv NOT_ROS_ROOT alternate text)', 'alternate text'),
+
+ # #1776
+ ('$(anon foo)', 'bar'),
+ ('$(anon foo)/baz', 'bar/baz'),
+ ('$(anon foo)/baz/$(anon foo)', 'bar/baz/bar'),
+
+ # arg
+ ('$(arg fuga)', 'hoge'),
+ ('$(arg fuga)$(arg fuga)', 'hogehoge'),
+ ('$(arg car)$(arg fuga)', 'cdrhoge'),
+ ('$(arg fuga)hoge', 'hogehoge'),
+ ]
+ for arg, val in tests:
+ self.assertEquals(val, resolve_args(arg, context=context))
+
+ # more #1776
+ r = resolve_args('$(anon foo)/bar')
+ self.assert_('/bar' in r)
+ self.failIf('$(anon foo)' in r)
+
+
+ # test against strings that should not match
+ noop_tests = [
+ '$(find rospy', '$find rospy', '', ' ', 'noop', 'find rospy', 'env ROS_ROOT', '$$', ')', '(', '()',
+ None,
+ ]
+ for t in noop_tests:
+ self.assertEquals(t, resolve_args(t))
+ failures = [
+ '$((find rospy))', '$(find $rospy)',
+ '$(find)', '$(find rospy roslib)', '$(export rospy)',
+ '$(env)', '$(env ROS_ROOT alternate)',
+ '$(env NOT_SET)',
+ '$(optenv)',
+ '$(anon)',
+ '$(anon foo bar)',
+ ]
+ for f in failures:
+ try:
+ resolve_args(f)
+ self.fail("resolve_args(%s) should have failed"%f)
+ except SubstitutionException: pass
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_substitution_args', SubArgsTest, coverage_packages=['roslib.substitution_args'])
+
diff --git a/test/test_roslib/test/test_roslib_xmlrpc.py b/test/test_roslib/test/test_roslib_xmlrpc.py
new file mode 100644
index 00000000..8cc28f3e
--- /dev/null
+++ b/test/test_roslib/test/test_roslib_xmlrpc.py
@@ -0,0 +1,71 @@
+# Software License Agreement (BSD License)
+#
+# Copyright (c) 2009, Willow Garage, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Willow Garage, Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+import roslib; roslib.load_manifest('test_roslib')
+
+import os
+import struct
+import sys
+import unittest
+
+import rosunit
+
+class RoslibXmlrpcTest(unittest.TestCase):
+
+ def test_XmlRpcHandler(self):
+ from roslib.xmlrpc import XmlRpcHandler
+ # tripwire
+ h = XmlRpcHandler()
+ # noop
+ h._ready('http://localhost:1234')
+ def test_XmlRpcNode(self):
+ from roslib.xmlrpc import XmlRpcNode
+ # not a very comprehensive test (yet)
+ #port, handler
+ tests = [
+ (None, None, None),
+ (8080, None, 8080),
+ ('8080', None, 8080),
+ (u'8080', None, 8080),
+ ]
+ for port, handler,true_port in tests:
+ n = XmlRpcNode(port, handler)
+ self.assertEquals(true_port, n.port)
+ self.assertEquals(handler, n.handler)
+ self.assertEquals(None, n.uri)
+ self.assertEquals(None, n.server)
+ n.set_uri('http://fake:1234')
+ self.assertEquals('http://fake:1234', n.uri)
+
+
+if __name__ == '__main__':
+ rosunit.unitrun('test_roslib', 'test_xmlrpc', RoslibXmlrpcTest, coverage_packages=['roslib.xmlrpc'])
+
diff --git a/test/test_roslib/test/utest.cpp b/test/test_roslib/test/utest.cpp
new file mode 100644
index 00000000..f03998ae
--- /dev/null
+++ b/test/test_roslib/test/utest.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2008, Willow Garage, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Willow Garage, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Author: Brian Gerkey */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ros/package.h"
+
+void string_split(const std::string &s, std::vector &t, const std::string &d)
+{ t.clear();
+ size_t start = 0, end;
+ while ((end = s.find_first_of(d, start)) != std::string::npos)
+ {
+ if((end-start) > 0)
+ t.push_back(s.substr(start, end-start));
+ start = end + 1;
+ }
+ if(start < s.size())
+ t.push_back(s.substr(start));
+}
+
+char g_rr_buf[1024];
+void set_env_vars(void)
+{
+ // Point ROS_PACKAGE_PATH at the test_roslib directory, and point
+ // ROS_ROOT into an empty directory.
+ getcwd(g_rr_buf, sizeof(g_rr_buf));
+ setenv("ROS_PACKAGE_PATH", g_rr_buf, 1);
+ strncpy(g_rr_buf+strlen(g_rr_buf), "/tmp.XXXXXX", sizeof(g_rr_buf)-strlen(g_rr_buf)-1);
+ g_rr_buf[sizeof(g_rr_buf)-1] = '\0';
+ mkdtemp(g_rr_buf);
+ setenv("ROS_ROOT", g_rr_buf, 1);
+}
+void cleanup_env_vars(void)
+{
+ // Remove the empty directory that we created in set_env_vars().
+ rmdir(g_rr_buf);
+ memset(g_rr_buf, 0, sizeof(g_rr_buf));
+}
+
+TEST(roslib, commandListNames)
+{
+ set_env_vars();
+
+ std::string output = ros::package::command("list-names");
+ std::vector output_list;
+ string_split(output, output_list, "\n");
+ ASSERT_EQ((int)output_list.size(), 1);
+ ASSERT_STREQ(output_list[0].c_str(), "test_roslib");
+
+ cleanup_env_vars();
+}
+
+TEST(roslib, commandList)
+{
+ set_env_vars();
+
+ std::string output = ros::package::command("list");
+ std::vector output_list;
+ std::vector name_path;
+ string_split(output, output_list, "\n");
+ ASSERT_EQ((int)output_list.size(), 1);
+ string_split(output_list[0], name_path, " ");
+ ASSERT_EQ((int)name_path.size(), 2);
+ ASSERT_STREQ(name_path[0].c_str(), "test_roslib");
+
+ cleanup_env_vars();
+}
+
+TEST(roslib, getAll)
+{
+ set_env_vars();
+
+ std::vector output_list;
+ ASSERT_TRUE(ros::package::getAll(output_list));
+ ASSERT_EQ((int)output_list.size(), 1);
+ ASSERT_STREQ(output_list[0].c_str(), "test_roslib");
+
+ cleanup_env_vars();
+}
+
+void
+roslib_caller()
+{
+ struct timespec ts = {0, 100000};
+ std::string output;
+ for(int i=0;i<100;i++)
+ {
+ output = ros::package::command("plugins --attrib=foo test_roslib");
+ nanosleep(&ts, NULL);
+ }
+}
+
+TEST(roslib, concurrent_access)
+{
+ set_env_vars();
+ const int size = 10;
+ boost::thread t[size];
+ for(int i=0;i