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