porting tests from test_roslib into roslib package

This commit is contained in:
Ken Conley 2012-01-04 23:25:43 +00:00
parent 4cde9e9262
commit aea291debc
42 changed files with 2198 additions and 182 deletions

View File

@ -561,185 +561,3 @@ def _safe_load_manifest(p):
return roslib.manifest.load_manifest(p)
except:
return roslib.manifest.Manifest()
class ROSPackages(object):
"""
UNSTABLE/EXPERIMENTAL
Utility class for querying properties about ROS packages. This
should be used when querying properties about multiple
packages. ROSPackages caches information about packages, which
enables it to have higher performance than alternatives like
shelling out to rospack.
Example::
rp = ROSPackages()
d = rp.depends1(['roscpp', 'rospy'])
print d['roscpp']
d = rp.rosdeps(['roscpp', 'rospy'])
print d['rospy']
"""
def __init__(self):
self.manifests = {}
self._depends_cache = {}
self._rosdeps_cache = {}
def load_manifests(self, packages):
"""
Load manifests for specified packages into 'manifests' attribute.
@param packages: package names
@type packages: [str]
"""
if not type(packages) in [list, tuple]:
raise TypeError("packages must be list or tuple")
# load any manifests that we haven't already
to_load = [p for p in packages if not p in self.manifests]
if to_load:
_update_rospack_cache()
self.manifests.update(dict([(p, _safe_load_manifest(p)) for p in to_load]))
def depends1(self, packages):
"""
Collect all direct dependencies of specified packages into a
dictionary.
@param packages: package names
@type packages: [str]
@return: dictionary mapping package names to list of dependent package names.
@rtype: {str: [str]}
"""
self.load_manifests(packages)
map = {}
manifests = self.manifests
for pkg in packages:
map[pkg] = [d.package for d in manifests[pkg].depends]
return map
def depends(self, packages):
"""
Collect all dependencies of specified packages into a
dictionary.
@param packages: package names
@type packages: [str]
@return: dictionary mapping package names to list of dependent package names.
@rtype: {str: [str]}
"""
self.load_manifests(packages)
map = {}
for pkg in packages:
if pkg in self._depends_cache:
map[pkg] = self._depends_cache[pkg]
else:
# this will cache for future reference
map[pkg] = self._depends(pkg)
return map
def _depends(self, package):
"""
Compute recursive dependencies of a single package and cache
the result in self._depends_cache.
This is an internal routine. It assumes that
load_manifests() has already been invoked for package.
@param package: package name
@type package: str
@return: list of rosdeps
@rtype: [str]
"""
if package in self._depends_cache:
return self._depends_cache[package]
# assign key before recursive call to prevent infinite case
self._depends_cache[package] = s = set()
manifests = self.manifests
# take the union of all dependencies
pkgs = [p.package for p in manifests[package].depends]
self.load_manifests(pkgs)
for p in pkgs:
s.update(self._depends(p))
# add in our own deps
s.update(pkgs)
# cache the return value as a list
s = list(s)
self._depends_cache[package] = s
return s
def rosdeps0(self, packages):
"""
Collect rosdeps of specified packages into a dictionary.
@param packages: package names
@type packages: [str]
@return: dictionary mapping package names to list of rosdep names.
@rtype: {str: [str]}
"""
self.load_manifests(packages)
map = {}
manifests = self.manifests
for pkg in packages:
map[pkg] = [d.name for d in manifests[pkg].rosdeps]
return map
def rosdeps(self, packages):
"""
Collect all (recursive) dependencies of specified packages
into a dictionary.
@param packages: package names
@type packages: [str]
@return: dictionary mapping package names to list of dependent package names.
@rtype: {str: [str]}
"""
self.load_manifests(packages)
map = {}
for pkg in packages:
if pkg in self._rosdeps_cache:
map[pkg] = self._rosdeps_cache[pkg]
else:
# this will cache for future reference
map[pkg] = self._rosdeps(pkg)
return map
def _rosdeps(self, package):
"""
Compute recursive rosdeps of a single package and cache the
result in self._rosdeps_cache.
This is an internal routine. It assumes that
load_manifests() has already been invoked for package.
@param package: package name
@type package: str
@return: list of rosdeps
@rtype: [str]
"""
if package in self._rosdeps_cache:
return self._rosdeps_cache[package]
# set the key before recursive call to prevent infinite case
self._rosdeps_cache[package] = s = set()
manifests = self.manifests
# take the union of all dependencies
pkgs = [p.package for p in manifests[package].depends]
self.load_manifests(pkgs)
for p in pkgs:
s.update(self._rosdeps(p))
# add in our own deps
s.update([d.name for d in manifests[package].rosdeps])
# cache the return value as a list
s = list(s)
self._rosdeps_cache[package] = s
return s

View File

@ -188,6 +188,7 @@ def expand_to_packages(names, env=None):
if env is None:
env = os.environ
ros_paths = rospkg.get_ros_paths(env)
print "ROS_PATHS", ros_paths, env['ROS_PACKAGE_PATH']
rospack = rospkg.RosPack(ros_paths)
rosstack = rospkg.RosStack(ros_paths)
return rospkg.expand_to_packages(names, rospack, rosstack)

View File

4
core/roslib/test/fake_node.py Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env python
# this node only exists to test find_node functionality
print "hello"

View File

@ -0,0 +1,21 @@
<package>
<description brief="a brief description">Line 1
Line 2
</description>
<version>1.2.4</version> <!-- bad -->
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://pr.willowgarage.com/package/</url>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend package="pkgname" />
<depend package="common"/>
<export>
<cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>
<cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lrosthread -framework CoreServices"/>
</export>
<rosdep name="python" />
<rosdep name="bar" />
<rosdep name="baz" />
</package>

View File

@ -0,0 +1 @@
not xml

View File

@ -0,0 +1,20 @@
<notpackage>
<description brief="a brief description">Line 1
Line 2
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://pr.willowgarage.com/package/</url>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend package="pkgname" />
<depend package="common"/>
<export>
<cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>
<cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lrosthread -framework CoreServices"/>
</export>
<rosdep name="python" />
<rosdep name="bar" />
<rosdep name="baz" />
</notpackage>

View File

@ -0,0 +1,11 @@
<package>
<description brief="a brief description">Line 1
</description>
<description brief="a brief second description">Second description
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
</package>

View File

@ -0,0 +1,20 @@
<package>
<description brief="a brief description">Line 1
Line 2
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://pr.willowgarage.com/package/</url>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend package="pkgname" />
<depend package="common"/>
<export>
<cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>
<cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lrosthread -framework CoreServices"/>
</export>
<rosdep name="python" />
<rosdep name="bar" />
<rosdep name="baz" />
</package>

View File

@ -0,0 +1,13 @@
<stack>
<description brief="a brief description">Line 1
Line 2
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://ros.org/stack/</url>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend stack="stackname" />
<depend stack="common"/>
</stack>

View File

@ -0,0 +1,14 @@
<stack>
<description brief="a brief description">Line 1
Line 2
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://ros.org/stack/</url>
<version>1.2.3</version>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend stack="stackname" />
<depend stack="common"/>
</stack>

View File

@ -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 <vector>
#include <gtest/gtest.h>
#include <ros/package.h>
#include <sys/time.h>
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();
}

View File

@ -0,0 +1,14 @@
<package>
<description brief="bar">
bar
</description>
<author>Ken Conley</author>
<license>BSD</license>
<review status="unreviewed" notes=""/>
<url>http://ros.org/wiki/bar</url>
</package>

View File

@ -0,0 +1,14 @@
<package>
<description brief="foo">
foo
</description>
<author>Ken Conley</author>
<license>BSD</license>
<review status="unreviewed" notes=""/>
<url>http://ros.org/wiki/foo</url>
</package>

View File

@ -0,0 +1,14 @@
<package>
<description brief="foo">
foo
</description>
<author>Ken Conley</author>
<license>BSD</license>
<review status="unreviewed" notes=""/>
<url>http://ros.org/wiki/foo</url>
</package>

View File

@ -0,0 +1,8 @@
<package>
<description brief="roslib tests">
Unit tests verifying that roslib is operating as expected.
</description>
<author>none</author>
<license>BSD</license>
<platform os="test_os" version="test_version"/>
</package>

View File

@ -0,0 +1,6 @@
[nosetests]
with-xunit=1
with-coverage=1
cover-package=roslib
tests=test_roslib_manifest.py,test_roslib_names.py,test_roslib_packages.py,test_roslib_params.py, test_roslib.py, test_roslib_rosenv.py, test_roslib_stack_manifest.py, test_roslib_stacks.py, test_roslib_substitution_args.py, test_roslib_exceptions.py, test_roslib_manifestlib.py

View File

@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
set(ROSPACK_MAKEDIST true)
rosbuild_make_distribution(1.5.0-cmake)

View File

@ -0,0 +1,9 @@
<stack>
<description brief="bar">
bar
</description>
<author>Ken Conley</author>
<license>BSD</license>
</stack>

View File

@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
set(ROSPACK_MAKEDIST true)
rosbuild_make_distribution(1.5.0-cmake)

View File

@ -0,0 +1,14 @@
<package>
<description brief="foo_pkg">
foo_pkg
</description>
<author>Ken Conley</author>
<license>BSD</license>
<review status="unreviewed" notes=""/>
<url>http://ros.org/wiki/foo_pkg</url>
</package>

View File

@ -0,0 +1,14 @@
<package>
<description brief="foo_pkg_2">
foo_pkg_2
</description>
<author>Ken Conley</author>
<license>BSD</license>
<review status="unreviewed" notes=""/>
<url>http://ros.org/wiki/foo_pkg_2</url>
</package>

View File

@ -0,0 +1,12 @@
<stack>
<description brief="foo">
foo
</description>
<author>Ken Conley</author>
<version>
1.6.0-manifest
</version>
<license>BSD</license>
</stack>

View File

@ -0,0 +1,9 @@
<package>
<description brief="foo">
foo
</description>
<author>Ken Conley</author>
<license>BSD</license>
</package>

View File

@ -0,0 +1 @@
../stack_tests/s1

View File

@ -0,0 +1,11 @@
<package>
<description brief="roslib tests">
Fake
</description>
<author>No one</author>
<license>BSD</license>
<review status="test" notes=""/>
<depend package="roslib" />
<depend package="rosunit" />
</package>

View File

@ -0,0 +1,9 @@
<stack>
<description brief="bar">
bar
</description>
<author>Ken Conley</author>
<license>BSD</license>
</stack>

View File

@ -0,0 +1,9 @@
<stack>
<description brief="bar">
bar
</description>
<author>Ken Conley</author>
<license>BSD</license>
</stack>

View File

@ -0,0 +1,11 @@
<package>
<description brief="roslib tests">
Fake
</description>
<author>No one</author>
<license>BSD</license>
<review status="test" notes=""/>
<depend package="roslib" />
<depend package="rosunit" />
</package>

View File

@ -0,0 +1,9 @@
<stack>
<description brief="foo">
foo
</description>
<author>Ken Conley</author>
<license>BSD</license>
</stack>

View File

@ -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 os
import sys
def test_load_manifest():
# this is a bit of a noop as it's a prerequisite of running with rosunit
import roslib
roslib.load_manifest('roslib')
def test_interactive():
import roslib
# make sure that it's part of high-level API
assert not roslib.is_interactive(), "interactive should be false by default"
for v in [True, False]:
roslib.set_interactive(v)
assert v == roslib.is_interactive()

View File

@ -0,0 +1,38 @@
# 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 os
import sys
def test_exceptions():
from roslib.exceptions import ROSLibException
assert isinstance(ROSLibException(), Exception)

View File

@ -0,0 +1,172 @@
# 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 os
import sys
import unittest
import roslib
def get_test_path():
return os.path.abspath(os.path.dirname(__file__))
class RoslibManifestTest(unittest.TestCase):
def test_ManifestException(self):
from roslib.manifest import ManifestException
self.assert_(isinstance(ManifestException(), Exception))
def test_Depend(self):
from roslib.manifestlib import Depend, ManifestException
for bad in [None, '']:
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('<depend package="roslib" />',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, '']:
try:
rd = ROSDep(bad)
self.fail("should have failed on [%s]"%bad)
except ValueError: pass
rd = ROSDep('python')
self.assertEquals('<rosdep name="python" />',rd.xml())
def test_VersionControl(self):
from roslib.manifest import VersionControl, ManifestException
ros_svn = 'https://ros.svn.sf.net/svnroot'
bad = [
(None, ros_svn),
]
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, '<versioncontrol type="svn" url="%s" />'%ros_svn),
('cvs', None, '<versioncontrol type="cvs" />'),
]
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(get_test_path(), '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
base_p = os.path.join(get_test_path(), '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 = """<package>
<description brief="a brief description">Line 1
Line 2
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://pr.willowgarage.com/package/</url>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend package="pkgname" />
<depend package="common"/>
<export>
<cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>
<cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lrosthread -framework CoreServices"/>
</export>
<rosdep name="python" />
<rosdep name="bar" />
<rosdep name="baz" />
<rosbuild2>
<depend thirdparty="thisshouldbeokay"/>
</rosbuild2>
</package>"""

View File

@ -0,0 +1,305 @@
# 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 os
import struct
import sys
import unittest
import roslib
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, '']:
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('<platform os="ubuntu" version="8.04"/>',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('<platform os="OS X" version="10.6" notes="macports"/>',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, '']:
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('<depend package="roslib" />',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, '']:
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('<depend stack="common" />',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, '']:
try:
rd = ROSDep(bad)
self.fail("should have failed on [%s]"%bad)
except ValueError: pass
rd = ROSDep('python')
self.assertEquals('<rosdep name="python" />',rd.xml())
def test_VersionControl(self):
from roslib.manifestlib import VersionControl, ManifestException
ros_svn = 'https://ros.svn.sf.net/svnroot'
bad = [
(None, ros_svn),
]
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, '<versioncontrol type="svn" url="%s" />'%ros_svn),
('cvs', None, '<versioncontrol type="cvs" />'),
]
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 _subtest_parse_stack_version(self, m):
self.assertEquals("1.2.3", m.version)
def test_parse_example1_file(self):
from roslib.manifestlib import parse_file, _Manifest
p = os.path.join(get_test_path(), 'manifest_tests', 'example1.xml')
self._subtest_parse_example1(parse_file(_Manifest(), p))
p = os.path.join(get_test_path(), 'manifest_tests', 'stack_example1.xml')
self._subtest_parse_stack_example1(parse_file(_Manifest('stack'), p))
p = os.path.join(get_test_path(), 'manifest_tests', 'stack_version.xml')
self._subtest_parse_stack_version(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
base_p = os.path.join(get_test_path(), '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 = """<package>
<description brief="a brief description">Line 1
Line 2
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://pr.willowgarage.com/package/</url>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend package="pkgname" />
<depend package="common"/>
<export>
<cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>
<cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lrosthread -framework CoreServices"/>
</export>
<rosdep name="python" />
<rosdep name="bar" />
<rosdep name="baz" />
<platform os="ubuntu" version="8.04" />
<platform os="OS X" version="10.6" notes="macports" />
<rosbuild2>
<depend thirdparty="thisshouldbeokay"/>
</rosbuild2>
</package>"""
STACK_EXAMPLE1 = """<stack>
<description brief="a brief description">Line 1
Line 2
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://ros.org/stack/</url>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend stack="stackname" />
<depend stack="common"/>
</stack>"""
STACK_INVALID1 = """<stack>
<description brief="a brief description">Line 1</description>
<author>The authors</author>
<license>Public Domain</license>
<rosdep name="python" />
</stack>"""
STACK_INVALID2 = """<stack>
<description brief="a brief description">Line 1</description>
<author>The authors</author>
<license>Public Domain</license>
<export>
<cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>
<cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lrosthread -framework CoreServices"/>
</export>
</stack>"""
def get_test_path():
return os.path.abspath(os.path.dirname(__file__))

View File

@ -0,0 +1,324 @@
# 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 os
import sys
import unittest
import roslib.names
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_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))

View File

@ -0,0 +1,93 @@
# 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 os
import struct
import sys
import unittest
import roslib.packages
class RoslibPackagesTest(unittest.TestCase):
def test_list_pkgs_by_path(self):
from roslib.packages import list_pkgs_by_path
# regression test for bug found where list_pkgs_by_path returns empty package name if path is a package and path is a relpath
d = roslib.packages.get_pkg_dir('roslib')
os.chdir(d)
self.assertEquals(['roslib'], list_pkgs_by_path('.'))
self.assertEquals(set(['bar', 'foo']), set(list_pkgs_by_path(os.path.join('test', 'package_tests'))))
self.assertEquals(set(['bar', 'foo']), set(list_pkgs_by_path(os.path.join('test', 'package_tests', 'p1'))))
self.assertEquals(['foo'], list_pkgs_by_path(os.path.join('test', 'package_tests', 'p1', 'foo')))
self.assertEquals([], list_pkgs_by_path(os.path.join('bin')))
def test_find_node(self):
import roslib.packages
d = roslib.packages.get_pkg_dir('roslib')
p = os.path.join(d, 'test', 'fake_node.py')
self.assertEquals(p, roslib.packages.find_node('roslib', 'fake_node.py'))
self.assertEquals(None, roslib.packages.find_node('roslib', 'not_a_node'))
def test_get_pkg_dir(self):
import roslib.packages
import roslib.rospack
path = roslib.rospack.rospackexec(['find', 'roslib'])
self.assertEquals(path, roslib.packages.get_pkg_dir('roslib'))
try:
self.assertEquals(path, roslib.packages.get_pkg_dir('fake_roslib'))
self.fail("should have raised")
except roslib.packages.InvalidROSPkgException: pass
def test_get_dir_pkg(self):
import roslib.packages
path = get_roslib_path()
res = roslib.packages.get_dir_pkg(path)
res = (os.path.realpath(res[0]), res[1])
self.assertEquals((path, 'roslib'), res)
res = roslib.packages.get_dir_pkg(os.path.join(path, 'test'))
res = (os.path.realpath(res[0]), res[1])
self.assertEquals((path, 'roslib'), res)
# must fail on parent of roslib
self.assertEquals((None, None), roslib.packages.get_dir_pkg(os.path.dirname(path)))
def get_roslib_path():
return os.path.abspath(os.path.join(get_test_path(), '..'))
def get_test_path():
return os.path.abspath(os.path.dirname(__file__))

View File

@ -0,0 +1,55 @@
# 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 os
import sys
import unittest
import roslib.names
class ParamsTest(unittest.TestCase):
def test_load_param_mappings(self):
from roslib.params import load_command_line_node_params
self.assertEquals({}, load_command_line_node_params([]))
self.assertEquals({}, load_command_line_node_params(['foo']))
self.assertEquals({}, load_command_line_node_params(['_foo']))
self.assertEquals({}, load_command_line_node_params([':=']))
self.assertEquals({}, load_command_line_node_params([':=:=']))
self.assertEquals({}, load_command_line_node_params(['_f:=']))
self.assertEquals({}, load_command_line_node_params([':=b']))
self.assertEquals({}, load_command_line_node_params(['_foo:=_bar:=baz']))
self.assertEquals({'foo': 'bar'}, load_command_line_node_params(['_foo:=bar']))
self.assertEquals({'foo': 'bar'}, load_command_line_node_params(['./f', '-x', '--blah', '_foo:=bar']))
self.assertEquals({'a': 'one', 'b': 2, 'c': 3.0, 'd':[1,2,3,4]}, load_command_line_node_params(['_c:=3.0', '_c:=', ':=3', '_a:=one', '_b:=2', '_d:=[1,2,3,4]']))

View File

@ -0,0 +1,150 @@
# 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 os
import sys
import unittest
import roslib.rosenv
class EnvTest(unittest.TestCase):
def test_get_ros_root(self):
from roslib.rosenv import get_ros_root
self.assertEquals(None, get_ros_root(required=False, env={}))
self.assertEquals(None, get_ros_root(False, {}))
try:
get_ros_root(required=True, env={})
self.fail("get_ros_root should have failed")
except: pass
env = {'ROS_ROOT': '/fake/path'}
self.assertEquals('/fake/path', get_ros_root(required=False, env=env))
try:
get_ros_root(required=True, env=env)
self.fail("get_ros_root should have failed")
except: pass
real_ros_root = get_ros_root(required=True)
# make sure that ros root is a directory
p = os.path.join(real_ros_root, 'Makefile')
env = {'ROS_ROOT': p}
self.assertEquals(p, get_ros_root(required=False, env=env))
try:
get_ros_root(required=True, env=env)
self.fail("get_ros_root should have failed")
except: pass
def test_get_ros_package_path(self):
from roslib.rosenv import get_ros_package_path
self.assertEquals(None, get_ros_package_path(required=False, env={}))
self.assertEquals(None, get_ros_package_path(False, {}))
try:
get_ros_package_path(required=True, env={})
self.fail("get_ros_package_path should have raised")
except: pass
env = {'ROS_PACKAGE_PATH': ':'}
self.assertEquals(':', get_ros_package_path(True, env=env))
self.assertEquals(':', get_ros_package_path(False, env=env))
# trip-wire tests. Cannot guarantee that ROS_PACKAGE_PATH is set
# to valid value on test machine, just make sure logic doesn't crash
self.assertEquals(os.environ.get('ROS_PACKAGE_PATH', None), get_ros_package_path(required=False))
def test_get_ros_master_uri(self):
from roslib.rosenv import get_master_uri
self.assertEquals(None, get_master_uri(required=False, env={}))
self.assertEquals(None, get_master_uri(False, {}))
try:
get_master_uri(required=True, env={})
self.fail("get_ros_package_path should have raised")
except: pass
env = {'ROS_MASTER_URI': 'http://localhost:1234'}
self.assertEquals('http://localhost:1234', get_master_uri(True, env=env))
self.assertEquals('http://localhost:1234', get_master_uri(False, env=env))
argv = ['__master:=http://localhost:5678']
self.assertEquals('http://localhost:5678', get_master_uri(False, env=env, argv=argv))
try:
argv = ['__master:=http://localhost:5678:=http://localhost:1234']
get_master_uri(required=False, env=env, argv=argv)
self.fail("should have thrown")
except roslib.rosenv.ROSEnvException: pass
try:
argv = ['__master:=']
get_master_uri(False, env=env, argv=argv)
self.fail("should have thrown")
except roslib.rosenv.ROSEnvException: pass
# make sure test works with os.environ
self.assertEquals(os.environ.get('ROS_MASTER_URI', None), get_master_uri(required=False))
def test_get_test_results_dir(self):
from roslib.rosenv import get_ros_root, get_test_results_dir
import tempfile, os
base = tempfile.gettempdir()
ros_test_results_dir = os.path.join(base, 'ros_test_results_dir')
ros_home_dir = os.path.join(base, 'ros_home_dir')
home_dir = os.path.expanduser('~')
# ROS_TEST_RESULTS_DIR has precedence
env = {'ROS_ROOT': get_ros_root(), 'ROS_TEST_RESULTS_DIR': ros_test_results_dir, 'ROS_HOME': ros_home_dir }
self.assertEquals(ros_test_results_dir, get_test_results_dir(env=env))
env = {'ROS_ROOT': get_ros_root(), 'ROS_HOME': ros_home_dir }
self.assertEquals(os.path.join(ros_home_dir, 'test_results'), get_test_results_dir(env=env))
env = {'ROS_ROOT': get_ros_root()}
self.assertEquals(os.path.join(home_dir, '.ros', 'test_results'), get_test_results_dir(env=env))
# test default assignment of env. Don't both checking return value as we would duplicate get_test_results_dir
self.assert_(get_test_results_dir() is not None)
def test_get_ros_home(self):
from roslib.rosenv import get_ros_root, get_ros_home
import tempfile, os
base = tempfile.gettempdir()
ros_home_dir = os.path.join(base, 'ros_home_dir')
home_dir = os.path.expanduser('~')
# ROS_HOME has precedence
env = {'ROS_ROOT': get_ros_root(), 'ROS_HOME': ros_home_dir }
self.assertEquals(ros_home_dir, get_ros_home(env=env))
env = {'ROS_ROOT': get_ros_root()}
self.assertEquals(os.path.join(home_dir, '.ros'), get_ros_home(env=env))
# test default assignment of env. Don't both checking return value
self.assert_(get_ros_home() is not None)

View File

@ -0,0 +1,123 @@
# 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 os
import sys
import unittest
import roslib
def get_test_path():
return os.path.abspath(os.path.dirname(__file__))
class RoslibStackManifestTest(unittest.TestCase):
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 _subtest_parse_stack_version(self, m):
self.assertEquals("1.2.3", m.version)
def test_parse_example1_file(self):
from roslib.stack_manifest import parse_file, StackManifest
p = os.path.join(get_test_path(), 'manifest_tests', 'stack_example1.xml')
self._subtest_parse_stack_example1(parse_file(p))
p = os.path.join(get_test_path(), 'manifest_tests', 'stack_version.xml')
self._subtest_parse_stack_version(parse_file(p))
def test_parse_example1_string(self):
from roslib.manifestlib import parse, _Manifest
self._subtest_parse_stack_example1(parse(_Manifest('stack'), STACK_EXAMPLE1))
def test_StackManifest(self):
from roslib.stack_manifest import StackManifest
m = StackManifest()
self.assertEquals('stack', m._type)
def test_StackManifest_str(self):
# just make sure it doesn't crash
from roslib.stack_manifest import parse
str(parse(STACK_EXAMPLE1))
def test_StackManifest_xml(self):
from roslib.stack_manifest import parse, StackManifest
m = parse(STACK_EXAMPLE1)
self._subtest_parse_stack_example1(m)
# verify roundtrip
m2 = parse(m.xml())
self._subtest_parse_stack_example1(m2)
# bad file examples should be more like the roslaunch tests where there is just 1 thing wrong
STACK_EXAMPLE1 = """<stack>
<description brief="a brief description">Line 1
Line 2
</description>
<author>The authors
go here</author>
<license>Public Domain
with other stuff</license>
<url>http://ros.org/stack/</url>
<logo>http://www.willowgarage.com/files/willowgarage/robot10.jpg</logo>
<depend stack="stackname" />
<depend stack="common"/>
</stack>"""
STACK_INVALID1 = """<stack>
<description brief="a brief description">Line 1</description>
<author>The authors</author>
<license>Public Domain</license>
<rosdep name="python" />
</stack>"""
STACK_INVALID2 = """<stack>
<description brief="a brief description">Line 1</description>
<author>The authors</author>
<license>Public Domain</license>
<export>
<cpp cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lros"/>
<cpp os="osx" cflags="-I${prefix}/include" lflags="-L${prefix}/lib -lrosthread -framework CoreServices"/>
</export>
</stack>"""

View File

@ -0,0 +1,243 @@
# 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 os
import sys
import unittest
import roslib
import rospkg
class RoslibStacksTest(unittest.TestCase):
def test_stack_of(self):
import roslib.packages
from roslib.stacks import stack_of
self.assertEquals('ros', stack_of('roslib'))
# due to caching, test twice
self.assertEquals('ros', stack_of('roslib'))
try:
stack_of('fake_roslib')
self.fail("should have failed")
except roslib.packages.InvalidROSPkgException:
pass
# test unary
test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests_unary')
env = os.environ.copy()
env['ROS_PACKAGE_PATH'] = test_dir
for s in ['foo', 'bar']:
self.assertEquals(s, stack_of(s, env=env))
def test_list_stacks(self):
from roslib.stacks import list_stacks
l = list_stacks()
self.assert_('ros' 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))
# test with env
test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests', 's1')
env = os.environ.copy()
env['ROS_PACKAGE_PATH'] = test_dir
self.assertEquals(set(['ros', 'foo', 'bar']), set(list_stacks(env=env)))
def test_list_stacks_by_path(self):
from roslib.stacks import list_stacks_by_path
# test with the ros stack
rr = rospkg.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('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('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('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('roslib'), 'test', 'stack_tests2')
self.assertEquals(set(['foo', 'bar']), set(list_stacks_by_path(test_dir)))
def test_list_stacks_by_path_unary(self):
from roslib.stacks import list_stacks_by_path
# test with synthetic stacks
test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests_unary')
self.assertEquals(set(['bar', 'foo', 'baz']), set(list_stacks_by_path(test_dir)))
def test_get_stack_dir_unary(self):
# now manipulate the environment to test precedence
# - save original RPP as we popen rosstack in other tests
d = roslib.packages.get_pkg_dir('roslib')
d = os.path.join(d, 'test', 'stack_tests_unary')
s1_d = os.path.join(d, 's1')
rpp = rospkg.get_ros_package_path()
try:
paths = [d]
os.environ[rospkg.environment.ROS_PACKAGE_PATH] = os.pathsep.join(paths)
self.assertEquals(os.path.join(s1_d, 'foo'), roslib.stacks.get_stack_dir('foo'))
self.assertEquals(os.path.join(s1_d, 'bar'), roslib.stacks.get_stack_dir('bar'))
self.assertEquals(os.path.join(s1_d, 'baz'), roslib.stacks.get_stack_dir('baz'))
finally:
#restore rpp
if rpp is not None:
os.environ[rospkg.environment.ROS_PACKAGE_PATH] = rpp
else:
del os.environ[rospkg.environment.ROS_PACKAGE_PATH]
def test_get_stack_dir(self):
import roslib.packages
from roslib.stacks import get_stack_dir, InvalidROSStackException, list_stacks
self.assertEquals(rospkg.get_ros_root(), get_stack_dir('ros'))
try:
get_stack_dir('non_existent')
self.fail("should have raised")
except roslib.stacks.InvalidROSStackException:
pass
# now manipulate the environment to test precedence
# - save original RPP as we popen rosstack in other tests
rpp = os.environ.get(rospkg.environment.ROS_PACKAGE_PATH, None)
try:
d = roslib.packages.get_pkg_dir('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[rospkg.environment.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[rospkg.environment.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[rospkg.environment.ROS_PACKAGE_PATH] = rpp
else:
del os.environ[rospkg.environment.ROS_PACKAGE_PATH]
def test_expand_to_packages_unary(self):
# test unary
test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests_unary')
env = os.environ.copy()
env[rospkg.environment.ROS_PACKAGE_PATH] = test_dir
from roslib.stacks import expand_to_packages
self.assertEquals((['foo'], []), expand_to_packages(['foo'], env=env))
self.assertEquals((['foo', 'bar'], []), expand_to_packages(['foo', 'bar'], env=env))
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'))
self.fail("expand_to_packages should only take in a list of strings")
except ValueError: pass
self.assertEquals(([], []), expand_to_packages([]))
self.assertEquals((['rosmake', 'roslib', 'roslib'], []), expand_to_packages(['rosmake', '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', 'bogus_one'])
self.assertEquals(['bogus_one'], invalid)
check = ['rosbuild', 'rosunit', 'roslib']
print valid
for c in check:
self.assert_(c in valid, "expected [%s] to be in ros expansion"%c)
def test_get_stack_version(self):
from roslib.stacks import get_stack_version
test_dir = os.path.join(get_test_path(), 'stack_tests', 's1')
env = os.environ.copy()
env[rospkg.environment.ROS_PACKAGE_PATH] = test_dir
# REP 109: stack.xml has precedence over CMakeLists.txt, version is whitespace stripped
self.assertEquals('1.6.0-manifest', roslib.stacks.get_stack_version('foo', env=env))
# REP 109: test fallback to CMakeLists.txt version
self.assertEquals('1.5.0-cmake', roslib.stacks.get_stack_version('bar', env=env))
if 0:
test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests_unary')
env = os.environ.copy()
env[rospkg.environment.ROS_PACKAGE_PATH] = test_dir
def get_test_path():
return os.path.abspath(os.path.dirname(__file__))

View File

@ -0,0 +1,163 @@
# 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 os
import sys
import unittest
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
roslib_dir = get_pkg_dir('roslib', required=True)
anon_context = {'foo': 'bar'}
arg_context = {'fuga': 'hoge', 'car': 'cdr'}
context = {'anon': anon_context, 'arg': arg_context }
tests = [
('$(find roslib)', roslib_dir),
('hello$(find roslib)', 'hello'+roslib_dir),
('$(find roslib )', roslib_dir),
('$$(find roslib )', '$'+roslib_dir),
('$( find roslib )', roslib_dir),
('$(find roslib )', roslib_dir),
('$(find roslib)$(find roslib)', roslib_dir+roslib_dir),
('$(find roslib)/foo/bar.xml', roslib_dir+os.sep+'foo'+os.sep+'bar.xml'),
(r'$(find roslib)\foo\bar.xml $(find roslib)\bar.xml', roslib_dir+os.sep+'foo'+os.sep+'bar.xml '+roslib_dir+os.sep+'bar.xml'),
('$(find roslib)\\foo\\bar.xml more/stuff\\here', roslib_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 roslib', '$find roslib', '', ' ', 'noop', 'find roslib', 'env ROS_ROOT', '$$', ')', '(', '()',
None,
]
for t in noop_tests:
self.assertEquals(t, resolve_args(t))
failures = [
'$((find roslib))', '$(find $roslib)',
'$(find)', '$(find roslib roslib)', '$(export roslib)',
'$(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

142
core/roslib/test/utest.cpp Normal file
View File

@ -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 <string>
#include <vector>
#include <stdlib.h>
#include <unistd.h>
#include <boost/thread.hpp>
#include <gtest/gtest.h>
#include "ros/package.h"
void string_split(const std::string &s, std::vector<std::string> &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 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<std::string> output_list;
string_split(output, output_list, "\n");
ASSERT_EQ((int)output_list.size(), 1);
ASSERT_STREQ(output_list[0].c_str(), "roslib");
cleanup_env_vars();
}
TEST(roslib, commandList)
{
set_env_vars();
std::string output = ros::package::command("list");
std::vector<std::string> output_list;
std::vector<std::string> 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(), "roslib");
cleanup_env_vars();
}
TEST(roslib, getAll)
{
set_env_vars();
std::vector<std::string> output_list;
ASSERT_TRUE(ros::package::getAll(output_list));
ASSERT_EQ((int)output_list.size(), 1);
ASSERT_STREQ(output_list[0].c_str(), "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 roslib");
nanosleep(&ts, NULL);
}
}
TEST(roslib, concurrent_access)
{
set_env_vars();
const int size = 10;
boost::thread t[size];
for(int i=0;i<size; i++)
t[i] = boost::thread(boost::bind(roslib_caller));
for(int i=0;i<size; i++)
t[i].join();
cleanup_env_vars();
}
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}