v01
This commit is contained in:
38
thirdparty/ros/ros_comm/test/test_rosmaster/CMakeLists.txt
vendored
Normal file
38
thirdparty/ros/ros_comm/test/test_rosmaster/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
|
||||
project(test_rosmaster)
|
||||
|
||||
find_package(catkin REQUIRED COMPONENTS genmsg rostest std_msgs)
|
||||
|
||||
if(CATKIN_ENABLE_TESTING)
|
||||
add_message_files(DIRECTORY msg
|
||||
FILES
|
||||
String.msg
|
||||
Arrays.msg
|
||||
CompositeA.msg CompositeB.msg Composite.msg
|
||||
Embed.msg Floats.msg Simple.msg
|
||||
RosmsgA.msg
|
||||
RosmsgB.msg
|
||||
RosmsgC.msg
|
||||
TestArrays.msg
|
||||
TestHeader.msg
|
||||
TestPrimitives.msg
|
||||
TestString.msg
|
||||
TVals.msg
|
||||
)
|
||||
add_service_files(DIRECTORY srv
|
||||
FILES
|
||||
AddTwoInts.srv
|
||||
RossrvA.srv
|
||||
RossrvB.srv
|
||||
)
|
||||
|
||||
generate_messages(DEPENDENCIES std_msgs)
|
||||
endif()
|
||||
|
||||
catkin_package()
|
||||
|
||||
if(CATKIN_ENABLE_TESTING)
|
||||
add_rostest(test/rosmaster.test)
|
||||
add_rostest(test/paramserver.test)
|
||||
endif()
|
||||
7
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Arrays.msg
vendored
Normal file
7
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Arrays.msg
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#for rostopic tests
|
||||
int8[] int8_arr
|
||||
uint8[] uint8_arr
|
||||
int32[] int32_arr
|
||||
uint32[] uint32_arr
|
||||
string[] string_arr
|
||||
time[] time_arr
|
||||
3
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Composite.msg
vendored
Normal file
3
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Composite.msg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# composite message. required for testing import calculation in generators
|
||||
CompositeA a
|
||||
CompositeB b
|
||||
6
thirdparty/ros/ros_comm/test/test_rosmaster/msg/CompositeA.msg
vendored
Normal file
6
thirdparty/ros/ros_comm/test/test_rosmaster/msg/CompositeA.msg
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# This represents an orientation in free space in quaternion form.
|
||||
|
||||
float64 x
|
||||
float64 y
|
||||
float64 z
|
||||
float64 w
|
||||
4
thirdparty/ros/ros_comm/test/test_rosmaster/msg/CompositeB.msg
vendored
Normal file
4
thirdparty/ros/ros_comm/test/test_rosmaster/msg/CompositeB.msg
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# copy of geometry_msgs/Point for testing
|
||||
float64 x
|
||||
float64 y
|
||||
float64 z
|
||||
3
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Embed.msg
vendored
Normal file
3
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Embed.msg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#for rostopic tests
|
||||
Simple simple
|
||||
Arrays arrays
|
||||
0
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Empty.msg
vendored
Normal file
0
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Empty.msg
vendored
Normal file
3
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Floats.msg
vendored
Normal file
3
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Floats.msg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# for rostopic tests
|
||||
float32 float32
|
||||
float64 float64
|
||||
1
thirdparty/ros/ros_comm/test/test_rosmaster/msg/RosmsgA.msg
vendored
Normal file
1
thirdparty/ros/ros_comm/test/test_rosmaster/msg/RosmsgA.msg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
int32 a
|
||||
1
thirdparty/ros/ros_comm/test/test_rosmaster/msg/RosmsgB.msg
vendored
Normal file
1
thirdparty/ros/ros_comm/test/test_rosmaster/msg/RosmsgB.msg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Empty empty
|
||||
2
thirdparty/ros/ros_comm/test/test_rosmaster/msg/RosmsgC.msg
vendored
Normal file
2
thirdparty/ros/ros_comm/test/test_rosmaster/msg/RosmsgC.msg
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
String s1
|
||||
String s2
|
||||
10
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Simple.msg
vendored
Normal file
10
thirdparty/ros/ros_comm/test/test_rosmaster/msg/Simple.msg
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# for rostopic tests
|
||||
byte b
|
||||
int16 int16
|
||||
int32 int32
|
||||
int64 int64
|
||||
char c
|
||||
uint16 uint16
|
||||
uint32 uint32
|
||||
uint64 uint64
|
||||
string str
|
||||
2
thirdparty/ros/ros_comm/test/test_rosmaster/msg/String.msg
vendored
Normal file
2
thirdparty/ros/ros_comm/test/test_rosmaster/msg/String.msg
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Copy of std_msgs/String.msg to avoid having tests require a dependency on std_msgs.
|
||||
string data
|
||||
3
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TVals.msg
vendored
Normal file
3
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TVals.msg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# for rostopic tests
|
||||
time t
|
||||
duration d
|
||||
10
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TestArrays.msg
vendored
Normal file
10
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TestArrays.msg
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# caller_id of most recent node to send this message
|
||||
string caller_id
|
||||
# caller_id of the original node to send this message
|
||||
string orig_caller_id
|
||||
|
||||
int32[] int32_array
|
||||
float32[] float32_array
|
||||
time[] time_array
|
||||
TestString[] test_string_array
|
||||
# TODO: array of arrays
|
||||
8
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TestHeader.msg
vendored
Normal file
8
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TestHeader.msg
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
Header header
|
||||
|
||||
# caller_id of most recent node to send this message
|
||||
string caller_id
|
||||
# caller_id of the original node to send this message
|
||||
string orig_caller_id
|
||||
|
||||
byte auto_header # autoset header on response
|
||||
21
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TestPrimitives.msg
vendored
Normal file
21
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TestPrimitives.msg
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Integration test message of all primitive types
|
||||
|
||||
# caller_id of most recent node to send this message
|
||||
string caller_id
|
||||
# caller_id of the original node to send this message
|
||||
string orig_caller_id
|
||||
|
||||
string str
|
||||
byte b
|
||||
int16 int16
|
||||
int32 int32
|
||||
int64 int64
|
||||
char c
|
||||
uint16 uint16
|
||||
uint32 uint32
|
||||
uint64 uint64
|
||||
float32 float32
|
||||
float64 float64
|
||||
time t
|
||||
duration d
|
||||
|
||||
6
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TestString.msg
vendored
Normal file
6
thirdparty/ros/ros_comm/test/test_rosmaster/msg/TestString.msg
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Integration test message
|
||||
# caller_id of most recent node to send this message
|
||||
string caller_id
|
||||
# caller_id of the original node to send this message
|
||||
string orig_caller_id
|
||||
string data
|
||||
21
thirdparty/ros/ros_comm/test/test_rosmaster/package.xml
vendored
Normal file
21
thirdparty/ros/ros_comm/test/test_rosmaster/package.xml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<package>
|
||||
<name>test_rosmaster</name>
|
||||
<version>1.12.14</version>
|
||||
<description>
|
||||
Tests for rosmaster which depend on rostest.
|
||||
</description>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>BSD</license>
|
||||
|
||||
<url>http://ros.org/wiki/rosmaster</url>
|
||||
<author>Ken Conley</author>
|
||||
|
||||
<buildtool_depend version_gte="0.5.68">catkin</buildtool_depend>
|
||||
|
||||
<build_depend>genmsg</build_depend>
|
||||
<build_depend>rosgraph</build_depend>
|
||||
<build_depend>rostest</build_depend>
|
||||
<build_depend>std_msgs</build_depend>
|
||||
|
||||
<test_depend>rosbuild</test_depend>
|
||||
</package>
|
||||
4
thirdparty/ros/ros_comm/test/test_rosmaster/srv/AddTwoInts.srv
vendored
Normal file
4
thirdparty/ros/ros_comm/test/test_rosmaster/srv/AddTwoInts.srv
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
int64 a
|
||||
int64 b
|
||||
---
|
||||
int64 sum
|
||||
3
thirdparty/ros/ros_comm/test/test_rosmaster/srv/RossrvA.srv
vendored
Normal file
3
thirdparty/ros/ros_comm/test/test_rosmaster/srv/RossrvA.srv
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
int32 areq
|
||||
---
|
||||
int32 aresp
|
||||
3
thirdparty/ros/ros_comm/test/test_rosmaster/srv/RossrvB.srv
vendored
Normal file
3
thirdparty/ros/ros_comm/test/test_rosmaster/srv/RossrvB.srv
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Empty empty
|
||||
---
|
||||
Empty empty
|
||||
0
thirdparty/ros/ros_comm/test/test_rosmaster/test/__init__.py
vendored
Normal file
0
thirdparty/ros/ros_comm/test/test_rosmaster/test/__init__.py
vendored
Normal file
4
thirdparty/ros/ros_comm/test/test_rosmaster/test/client_verification/rosjava_profile.yaml
vendored
Normal file
4
thirdparty/ros/ros_comm/test/test_rosmaster/test/client_verification/rosjava_profile.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
pubs:
|
||||
'/chatter_out': std_msgs/String
|
||||
'/int64': std_msgs/Int64
|
||||
subs: {}
|
||||
505
thirdparty/ros/ros_comm/test/test_rosmaster/test/client_verification/test_slave_api.py
vendored
Executable file
505
thirdparty/ros/ros_comm/test/test_rosmaster/test/client_verification/test_slave_api.py
vendored
Executable file
@@ -0,0 +1,505 @@
|
||||
#!/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.
|
||||
|
||||
# This is a rewrite of the old node API tests, which focus too much on
|
||||
# a completed node API and don't facilitate easy bring up of a new
|
||||
# client library.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import string
|
||||
import time
|
||||
import unittest
|
||||
try:
|
||||
from xmlrpc.client import Fault, ServerProxy
|
||||
except ImportError:
|
||||
from xmlrpclib import Fault, ServerProxy
|
||||
|
||||
import rosunit
|
||||
import rosgraph
|
||||
|
||||
TCPROS = 'TCPROS'
|
||||
|
||||
CALLER_ID = '/test_harness'
|
||||
TEST_NODE_NAME = '/test_node' #default
|
||||
|
||||
class TopicDescription(object):
|
||||
def __init__(self, topic_name, topic_type):
|
||||
self.topic_name = topic_name
|
||||
self.topic_type = topic_type
|
||||
|
||||
#validate topic
|
||||
if not rosgraph.names.is_legal_name(topic_name):
|
||||
raise ValueError('topic name: %s'%(topic_name))
|
||||
|
||||
# validate type
|
||||
p, t = topic_type.split('/')
|
||||
|
||||
class TopicDescriptionList(object):
|
||||
|
||||
def __init__(self, xmlrpcvalue):
|
||||
# [ [topic1, topicType1]...[topicN, topicTypeN]]]
|
||||
if not type(xmlrpcvalue) == list:
|
||||
raise ValueError("publications must be a list")
|
||||
self.topics = []
|
||||
for n, t in xmlrpcvalue:
|
||||
self.topics.append(TopicDescription(n, t))
|
||||
|
||||
def as_dict(self):
|
||||
d = {}
|
||||
for t in self.topics:
|
||||
d[t.topic_name] = t.topic_type
|
||||
return d
|
||||
|
||||
class TestSlaveApi(unittest.TestCase):
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
super(TestSlaveApi, self).__init__(*args)
|
||||
|
||||
self.ns = os.environ.get(rosgraph.ROS_NAMESPACE, rosgraph.names.GLOBALNS)
|
||||
|
||||
# load in name of test node
|
||||
self.test_node = 'test_node' #default
|
||||
self.required_pubs = TopicDescriptionList([])
|
||||
self.required_subs = TopicDescriptionList([])
|
||||
|
||||
for arg in sys.argv:
|
||||
if arg.startswith("--node="):
|
||||
self.test_node = arg[len("--node="):]
|
||||
if arg.startswith("--profile="):
|
||||
self.test_node_profile = arg[len("--profile="):]
|
||||
self.load_profile(self.test_node_profile)
|
||||
|
||||
# resolve
|
||||
self.test_node = rosgraph.names.ns_join(self.ns, self.test_node)
|
||||
|
||||
def load_profile(self, filename):
|
||||
import yaml
|
||||
with open(filename) as f:
|
||||
d = yaml.load(f)
|
||||
self.required_pubs = d.get('pubs', {})
|
||||
self.required_subs = d.get('subs', {})
|
||||
|
||||
def setUp(self):
|
||||
self.caller_id = CALLER_ID
|
||||
# retrieve handle on node
|
||||
# give ourselves 10 seconds for node to appear
|
||||
timeout_t = 10.0 + time.time()
|
||||
self.node_api = None
|
||||
self.master = rosgraph.Master(self.caller_id)
|
||||
while time.time() < timeout_t and not self.node_api:
|
||||
try:
|
||||
self.node_api = self.master.lookupNode(self.test_node)
|
||||
except:
|
||||
time.sleep(0.1)
|
||||
if not self.node_api:
|
||||
self.fail("master did not return XML-RPC API for [%s, %s]"%(self.caller_id, self.test_node))
|
||||
print "[%s] API = %s"%(self.test_node, self.node_api)
|
||||
self.assert_(self.node_api.startswith('http'))
|
||||
self.node = ServerProxy(self.node_api)
|
||||
|
||||
# hack: sleep for a couple seconds just in case the node is
|
||||
# still registering with the master.
|
||||
time.sleep(2.)
|
||||
|
||||
def apiSuccess(self, args):
|
||||
"""
|
||||
unit test assertion that fails if status code is not 1 and otherwise returns the value parameter.
|
||||
@param args: returnv value from ROS API call
|
||||
@type args: [int, str, val]
|
||||
@return: value parameter from args (arg[2] for master/slave API)
|
||||
"""
|
||||
self.assert_(len(args) == 3, "invalid API return value triplet: %s"%str(args))
|
||||
self.last_code, self.last_msg, self.last_val = args
|
||||
assert self.last_code == 1, "status code is not 1: %s"%self.last_msg
|
||||
return self.last_val
|
||||
|
||||
def apiFail(self, args):
|
||||
"""
|
||||
unit test assertions that fails if status code is not 0 and otherwise returns true.
|
||||
@param args: returnv value from ROS API call
|
||||
@type args: [int, str, val]
|
||||
@return: True if status code is 0
|
||||
"""
|
||||
self.assert_(len(args) == 3, "invalid API return value triplet: %s"%str(args))
|
||||
self.last_code, self.last_msg, self.last_val = args
|
||||
assert self.last_code == 0, "Call should have failed with status code 0: %s"%self.last_msg
|
||||
|
||||
def apiError(self, args, msg=None):
|
||||
"""
|
||||
unit test assertion that fails if status code is not -1 and otherwise returns true.
|
||||
@param args: returnv value from ROS API call
|
||||
@type args: [int, str, val]
|
||||
@return: True if status code is -1
|
||||
"""
|
||||
self.assert_(len(args) == 3, "invalid API return value triplet: %s"%str(args))
|
||||
self.last_code, self.last_msg, self.last_val = args
|
||||
if msg:
|
||||
assert self.last_code == -1, "%s (return msg was %s)"%(msg, self.last_msg)
|
||||
else:
|
||||
assert self.last_code == -1, "Call should have returned error -1 code: %s"%self.last_msg
|
||||
|
||||
def check_uri(self, uri):
|
||||
"""
|
||||
validates a URI as being http(s)
|
||||
"""
|
||||
import urlparse
|
||||
parsed = urlparse.urlparse(uri)
|
||||
self.assert_(parsed[0] in ['http', 'https'], 'protocol [%s] is [%s] invalid'%(parsed[0], uri))
|
||||
self.assert_(parsed[1], 'host missing [%s]'%uri)
|
||||
self.assert_(parsed.port, 'port missing/invalid [%s]'%uri)
|
||||
|
||||
def test_getPid(self):
|
||||
"""
|
||||
validate node.getPid(caller_id)
|
||||
"""
|
||||
# test success
|
||||
pid = self.apiSuccess(self.node.getPid(self.caller_id))
|
||||
self.assert_(pid > 0)
|
||||
|
||||
# test with bad arity: accept error or fault
|
||||
try:
|
||||
self.apiError(self.node.getPid())
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
def test_rosout(self):
|
||||
"""
|
||||
make sure rosout is in publication and connection list
|
||||
"""
|
||||
val = self.apiSuccess(self.node.getPublications(self.caller_id))
|
||||
pubs_d = TopicDescriptionList(val).as_dict()
|
||||
self.assertTrue('/rosout' in pubs_d, "node is not publishing to rosout")
|
||||
self.assertEquals('rosgraph_msgs/Log', pubs_d['/rosout'], "/rosout is not correct type")
|
||||
|
||||
def test_simtime(self):
|
||||
"""
|
||||
test that node obeys simtime (/Clock) contract
|
||||
|
||||
http://www.ros.org/wiki/Clock
|
||||
"""
|
||||
try:
|
||||
use_sim_time = self.master.getParam('/use_sim_time')
|
||||
except:
|
||||
use_sim_time = False
|
||||
|
||||
val = self.apiSuccess(self.node.getSubscriptions(self.caller_id))
|
||||
subs_d = TopicDescriptionList(val).as_dict()
|
||||
if use_sim_time:
|
||||
self.assertTrue('/clock' in subs_d, "node is not subscribing to clock")
|
||||
self.assertEquals('rosgraph_msgs/Clock', subs_d['/clock'], "/clock is not correct type")
|
||||
else:
|
||||
self.assertFalse('/clock' in subs_d, "node is subscribed to /clock even though /use_sim_time is false")
|
||||
|
||||
def test_getPublications(self):
|
||||
"""
|
||||
validate node.getPublications(caller_id)
|
||||
"""
|
||||
# test success
|
||||
pubs_value = self.apiSuccess(self.node.getPublications(self.caller_id))
|
||||
pubs = TopicDescriptionList(pubs_value)
|
||||
|
||||
pubs_dict = pubs.as_dict()
|
||||
# this is separately tested by test_rosout
|
||||
if '/rosout' in pubs_dict:
|
||||
del pubs_dict['/rosout']
|
||||
self.assertEquals(self.required_pubs, pubs_dict)
|
||||
|
||||
# test with bad arity: accept error or fault
|
||||
try:
|
||||
self.apiError(self.node.getPublications())
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(self.node.getPublications(self.caller_id, 'something extra'))
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
def test_getSubscriptions(self):
|
||||
"""
|
||||
validate node.getSubscriptions(caller_id)
|
||||
"""
|
||||
|
||||
# test success
|
||||
value = self.apiSuccess(self.node.getSubscriptions(self.caller_id))
|
||||
subs = TopicDescriptionList(value)
|
||||
|
||||
subs_dict = subs.as_dict()
|
||||
self.assertEquals(self.required_subs, subs_dict)
|
||||
|
||||
# test with bad arity: accept error or fault
|
||||
try:
|
||||
self.apiError(self.node.getSubscriptions())
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(self.node.getSubscriptions(self.caller_id, 'something extra'))
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
## validate node.paramUpdate(caller_id, key, value)
|
||||
def test_paramUpdate(self):
|
||||
node = self.node
|
||||
good_key = rosgraph.names.ns_join(self.ns, 'good_key')
|
||||
bad_key = rosgraph.names.ns_join(self.ns, 'bad_key')
|
||||
|
||||
# node is not subscribed to good_key (yet)
|
||||
self.apiError(node.paramUpdate(self.caller_id, good_key, 'good_value'))
|
||||
|
||||
# test bad key
|
||||
self.apiError(node.paramUpdate(self.caller_id, '', 'bad'))
|
||||
self.apiError(node.paramUpdate(self.caller_id, 'no_namespace', 'bad'))
|
||||
|
||||
# test with bad arity: accept error or fault
|
||||
try:
|
||||
self.apiError(node.paramUpdate(self.caller_id, bad_key))
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
try:
|
||||
self.apiError(node.paramUpdate(self.caller_id))
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
# we can't actually test success cases without forcing node to subscribe
|
||||
#self.apiSuccess(node.paramUpdate(self.caller_id, good_key, 1))
|
||||
#self.apiSuccess(node.paramUpdate(self.caller_id, good_key, True))
|
||||
#self.apiSuccess(node.paramUpdate(self.caller_id, good_key, 10.0))
|
||||
|
||||
def xtest_getUri(self):
|
||||
"""
|
||||
Future: validate node.getUri(caller_id). It would be nice to
|
||||
make this official API as it provides some debugging info.
|
||||
"""
|
||||
# test success
|
||||
self.check_uri(self.apiSuccess(self.node.getUri(self.caller_id)))
|
||||
|
||||
# test bad arity
|
||||
try:
|
||||
self.apiError(self.node.getUri(self.caller_id, 'bad'))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(self.node.getUri())
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
def test_getMasterUri(self):
|
||||
"""
|
||||
validate node.getMasterUri(caller_id)
|
||||
"""
|
||||
# test success
|
||||
uri = self.apiSuccess(self.node.getMasterUri(self.caller_id))
|
||||
self.check_uri(uri)
|
||||
|
||||
# check against env, canonicalize for comparison
|
||||
import urlparse
|
||||
master_env = rosgraph.get_master_uri()
|
||||
if not master_env.endswith('/'):
|
||||
master_env = master_env + '/'
|
||||
self.assertEquals(urlparse.urlparse(master_env), urlparse.urlparse(uri))
|
||||
|
||||
# test bad arity
|
||||
try:
|
||||
self.apiError(self.node.getMasterUri(self.caller_id, 'bad'))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(self.node.getMasterUri())
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
def test_publisherUpdate(self):
|
||||
"""
|
||||
validate node.publisherUpdate(caller_id, topic, uris)
|
||||
"""
|
||||
node = self.node
|
||||
probe_topic = rosgraph.names.ns_join(self.ns, 'probe_topic')
|
||||
fake_topic = rosgraph.names.ns_join(self.ns, 'fake_topic')
|
||||
|
||||
# test success
|
||||
# still success even if not actually interested in topic
|
||||
self.apiSuccess(node.publisherUpdate(self.caller_id, fake_topic,
|
||||
['http://localhost:1234', 'http://localhost:5678']))
|
||||
self.apiSuccess(node.publisherUpdate(self.caller_id, fake_topic,
|
||||
[]))
|
||||
# try it with it the /probe_topic, which will exercise some error branches in the client
|
||||
self.apiSuccess(node.publisherUpdate(self.caller_id, probe_topic,
|
||||
['http://unroutablefakeservice:1234']))
|
||||
# give it some time to make sure it's attempted contact
|
||||
time.sleep(1.0)
|
||||
# check that it's still there
|
||||
self.apiSuccess(node.publisherUpdate(self.caller_id, probe_topic,
|
||||
[]))
|
||||
|
||||
# test bad args
|
||||
try:
|
||||
self.apiError(node.publisherUpdate(self.caller_id, '/bad_topic', 'bad'))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.publisherUpdate(self.caller_id, '/bad_topic', 2))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.publisherUpdate(self.caller_id, '/bad_topic', False))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.publisherUpdate(self.caller_id, '/bad_topic', ['bad']))
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
# test bad arity
|
||||
try:
|
||||
self.apiError(node.publisherUpdate())
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.getBusStats(self.caller_id, 'bad'))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.getBusStats())
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
def check_TCPROS(self, protocol_params):
|
||||
self.assert_(protocol_params, "no protocol params returned")
|
||||
self.assert_(type(protocol_params) == list, "protocol params must be a list: %s"%protocol_params)
|
||||
self.assertEquals(3, len(protocol_params), "TCPROS params should have length 3: %s"%protocol_params)
|
||||
self.assertEquals(protocol_params[0], TCPROS)
|
||||
# expect ['TCPROS', 1.2.3.4, 1234]
|
||||
self.assertEquals(protocol_params[0], TCPROS)
|
||||
|
||||
def testRequestTopic(self):
|
||||
node = self.node
|
||||
protocols = [[TCPROS]]
|
||||
|
||||
publications = node.getPublications(self.caller_id)
|
||||
|
||||
topics = self.required_pubs.keys()
|
||||
probe_topic = topics[0] if topics else None
|
||||
fake_topic = rosgraph.names.ns_join(self.ns, 'fake_topic')
|
||||
|
||||
# currently only support TCPROS as we require all clients to support this
|
||||
protocols = [[TCPROS]]
|
||||
for topic in topics:
|
||||
self.check_TCPROS(self.apiSuccess(node.requestTopic(self.caller_id, topic, protocols)))
|
||||
protocols = [['FakeTransport', 1234, 5678], [TCPROS], ['AnotherFakeTransport']]
|
||||
# try each one more time, this time with more protocol choices
|
||||
for topic in topics:
|
||||
self.check_TCPROS(self.apiSuccess(node.requestTopic(self.caller_id, topic, protocols)))
|
||||
|
||||
# test bad arity
|
||||
if probe_topic:
|
||||
try:
|
||||
self.apiError(node.requestTopic(self.caller_id, probe_topic, protocols, 'extra stuff'))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.requestTopic(self.caller_id, probe_topic))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.requestTopic(self.caller_id))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.requestTopic())
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
# test bad args
|
||||
try:
|
||||
self.apiError(node.requestTopic(self.caller_id, 1, protocols))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.requestTopic(self.caller_id, '', protocols))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.requestTopic(self.caller_id, fake_topic, protocols))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(node.requestTopic(self.caller_id, probe_topic, 'fake-protocols'))
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
|
||||
def test_getBusInfo(self):
|
||||
#TODO: finish
|
||||
# there should be a connection to rosout
|
||||
|
||||
# test bad arity
|
||||
try:
|
||||
self.apiError(self.node.getBusInfo(self.caller_id, 'bad'))
|
||||
except Fault:
|
||||
pass
|
||||
try:
|
||||
self.apiError(self.node.getBusInfo())
|
||||
except Fault:
|
||||
pass
|
||||
|
||||
|
||||
## test the state of the master based on expected node registration
|
||||
def test_registrations(self):
|
||||
# setUp() ensures the node has registered with the master
|
||||
|
||||
# check actual URIs
|
||||
node_name = self.test_node
|
||||
pubs, subs, srvs = self.master.getSystemState()
|
||||
pub_topics = [t for t, _ in pubs]
|
||||
sub_topics = [t for t, _ in subs]
|
||||
|
||||
# make sure all required topics are registered
|
||||
for t in self.required_pubs:
|
||||
self.assert_(t in pub_topics, "node did not register publication %s on master"%(t))
|
||||
for t in self.required_subs:
|
||||
self.assert_(t in sub_topics, "node did not register subscription %s on master"%(t))
|
||||
|
||||
# check for node URI on master
|
||||
for topic, node_list in pubs:
|
||||
if topic in self.required_pubs:
|
||||
self.assert_(node_name in node_list, "%s not in %s"%(self.node_api, node_list))
|
||||
for topic, node_list in subs:
|
||||
if topic in self.required_subs:
|
||||
self.assert_(node_name in node_list, "%s not in %s"%(self.node_api, node_list))
|
||||
for service, srv_list in srvs:
|
||||
#TODO: no service tests yet
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
rosunit.unitrun('test_rosmaster', sys.argv[0], TestSlaveApi)
|
||||
468
thirdparty/ros/ros_comm/test/test_rosmaster/test/master.py
vendored
Normal file
468
thirdparty/ros/ros_comm/test/test_rosmaster/test/master.py
vendored
Normal file
@@ -0,0 +1,468 @@
|
||||
# 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: testSlave.py 1100 2008-05-29 20:23:54Z sfkwc $
|
||||
|
||||
import os
|
||||
import sys
|
||||
import string
|
||||
import time
|
||||
try:
|
||||
from xmlrpc.client import ServerProxy
|
||||
except ImportError:
|
||||
from xmlrpclib import ServerProxy
|
||||
|
||||
import rospy
|
||||
import rosgraph
|
||||
|
||||
from rosclient import *
|
||||
|
||||
NODE_INTEGRATION_NAME = "node_integration_test"
|
||||
|
||||
_name = None
|
||||
## set_node_name() must be called prior to the unit test so that the test harness knows its
|
||||
## ROS name.
|
||||
def set_node_name(name):
|
||||
global _name
|
||||
_name = name
|
||||
|
||||
# Have to try as hard as possible to not use rospy code in testing rospy code, so this is
|
||||
# a reimplementation of the caller ID spec so that NodeApiTestCase knows its name
|
||||
## reimplementation of caller ID spec separately from rospy
|
||||
def get_caller_id():
|
||||
if _name is None:
|
||||
raise Exception("set_node_name has not been called yet")
|
||||
ros_ns = os.environ.get(rosgraph.ROS_NAMESPACE, rosgraph.names.GLOBALNS)
|
||||
return rosgraph.names.ns_join(ros_ns, _name)
|
||||
|
||||
class _MasterTestCase(TestRosClient):
|
||||
|
||||
def __init__(self, *args):
|
||||
super(_MasterTestCase, self).__init__(*args)
|
||||
self.ns = os.environ.get(rosgraph.ROS_NAMESPACE, rosgraph.names.GLOBALNS)
|
||||
self.caller_id = get_caller_id()
|
||||
|
||||
def setUp(self):
|
||||
super(_MasterTestCase, self).setUp()
|
||||
self.master_uri = os.environ.get(rosgraph.ROS_MASTER_URI, None)
|
||||
self._checkUri(self.master_uri)
|
||||
self.master = ServerProxy(self.master_uri)
|
||||
|
||||
## validates a URI as being http(s)
|
||||
def _checkUri(self, uri):
|
||||
import urlparse
|
||||
parsed = urlparse.urlparse(uri)
|
||||
self.assert_(parsed[0] in ['http', 'https'], 'protocol [%s] in [%s] invalid'%(parsed[0], uri))
|
||||
self.assert_(parsed[1], 'host missing [%s]'%uri)
|
||||
if not sys.version.startswith('2.4'): #check not available on py24
|
||||
self.assert_(parsed.port, 'port missing/invalid [%s]'%uri)
|
||||
|
||||
## Expects a single test node to be running with name 'test_node' and subscribed to 'test_string'
|
||||
class MasterApiTestCase(_MasterTestCase):
|
||||
|
||||
## validate master.getMasterUri(caller_id)
|
||||
def _testGetMasterUri(self):
|
||||
# test with bad arity
|
||||
self.apiError(self.master.getMasterUri())
|
||||
# test success
|
||||
uri = self.apiSuccess(self.master.getMasterUri(self.caller_id))
|
||||
self._checkUri(uri)
|
||||
|
||||
# make sure we agree on ports
|
||||
import urlparse
|
||||
parsed = urlparse.urlparse(uri)
|
||||
parsed2 = urlparse.urlparse(self.master_uri)
|
||||
|
||||
self.assertEquals(parsed.port, parsed2.port, "expected ports do not match")
|
||||
|
||||
## validate master.getPid(caller_id)
|
||||
def _testGetPid(self):
|
||||
# test with bad arity
|
||||
self.apiError(self.master.getPid())
|
||||
# test success
|
||||
pid = self.apiSuccess(self.master.getPid(self.caller_id))
|
||||
self.assert_(pid > 0)
|
||||
|
||||
## validate master.getUri(caller_id)
|
||||
def _testGetUri(self):
|
||||
# test with bad arity
|
||||
self.apiError(self.master.getUri())
|
||||
# test success
|
||||
uri = self.apiSuccess(self.master.getUri(self.caller_id))
|
||||
self.assert_(type(uri) == str)
|
||||
|
||||
## common test subroutine of both register and unregister tests. registers the common test cases
|
||||
def _subTestRegisterServiceSuccess(self):
|
||||
master = self.master
|
||||
|
||||
caller_id = '/service_node'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
service_base = '/service'
|
||||
|
||||
# test success
|
||||
for i in range(0, 10):
|
||||
service_name = "%s-%s"%(service_base, i)
|
||||
service_api = 'rosrpc://localhost:123%s/'%i
|
||||
# register the service
|
||||
self.apiSuccess(master.registerService(caller_id, service_name, service_api, caller_api))
|
||||
# test master state
|
||||
val = self.apiSuccess(master.lookupService(caller_id, service_name))
|
||||
self.assertEquals(service_api, val)
|
||||
val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
|
||||
self.assertEquals(caller_api, val)
|
||||
|
||||
_, _, srvs = self.apiSuccess(master.getSystemState(self.caller_id))
|
||||
for j in range(0, i+1):
|
||||
jservice_name = "%s-%s"%(service_base, j)
|
||||
jentry = [jservice_name, [caller_id]]
|
||||
self.assert_(jentry in srvs, "master service list %s is missing %s"%(srvs, jentry))
|
||||
|
||||
# TODO: have to test subscriber callback
|
||||
# TODO: validate with getSystemState()
|
||||
|
||||
## validate master.registerService(caller_id, service, service_api, caller_api)
|
||||
def _testRegisterServiceSuccess(self):
|
||||
self._subTestRegisterServiceSuccess()
|
||||
|
||||
def _testUnregisterServiceSuccess(self):
|
||||
self._subTestRegisterServiceSuccess()
|
||||
master = self.master
|
||||
caller_id = '/service_node'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
service_base = '/service'
|
||||
|
||||
for i in range(0, 10):
|
||||
service_name = "%s-%s"%(service_base, i)
|
||||
service_api = 'rosrpc://localhost:123%s/'%i
|
||||
|
||||
# unregister the service
|
||||
code, msg, val = master.unregisterService(caller_id, service_name, service_api)
|
||||
self.assertEquals(code, 1, "code != 1, return message was [%s]"%msg)
|
||||
|
||||
# test the master state
|
||||
self.apiError(master.lookupService(self.caller_id, service_name), "master has a reference to unregistered service. message from master for unregister was [%s]"%msg)
|
||||
|
||||
if i < 9:
|
||||
val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
|
||||
self.assertEquals(caller_api, val, "master prematurely invalidated node entry for [%s] (lookupNode)"%caller_id)
|
||||
|
||||
_, _, srvs = self.apiSuccess(master.getSystemState(self.caller_id))
|
||||
for j in range(0, i+1):
|
||||
jservice_name = "%s-%s"%(service_base, j)
|
||||
jentry = [jservice_name, [caller_id]]
|
||||
self.assert_(jentry not in srvs, "master service list %s should not have %s"%(srvs, jentry))
|
||||
for j in range(i+1, 10):
|
||||
jservice_name = "%s-%s"%(service_base, j)
|
||||
jentry = [jservice_name, [caller_id]]
|
||||
self.assert_(jentry in srvs, "master service list %s is missing %s"%(srvs, jentry))
|
||||
|
||||
# TODO: have to test subscriber callback
|
||||
|
||||
# Master's state should be zero'd out now
|
||||
|
||||
# - #457 make sure that lookupNode isn't returning stale info
|
||||
self.apiError(master.lookupNode(self.caller_id, caller_id), "master has a stale reference to unregistered service node API")
|
||||
_, _, srvs = self.apiSuccess(master.getSystemState(self.caller_id))
|
||||
srvs = [s for s in srvs if not s[0].startswith('/rosout/') and not s[0].endswith('/get_loggers') and not s[0].endswith('/set_logger_level')]
|
||||
self.assertEquals(0, len(srvs), "all services should have been unregistered: %s"%srvs)
|
||||
|
||||
def _testRegisterServiceInvalid(self):
|
||||
master = self.master
|
||||
|
||||
service = '/service'
|
||||
service_api = 'rosrpc://localhost:1234/'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
|
||||
# test with bad arity
|
||||
self.apiError(master.registerService())
|
||||
self.apiError(master.registerService(self.caller_id, service))
|
||||
self.apiError(master.registerService(self.caller_id, service, service_api))
|
||||
|
||||
# test with bad args
|
||||
self.apiError(master.registerService(self.caller_id, '', service_api, caller_api))
|
||||
self.apiError(master.registerService(self.caller_id, service, '', caller_api))
|
||||
self.apiError(master.registerService(self.caller_id, service, service_api, ''))
|
||||
|
||||
def _testUnregisterServiceInvalid(self):
|
||||
master = self.master
|
||||
|
||||
service = '/service'
|
||||
service_api = 'rosrpc://localhost:1234/'
|
||||
|
||||
# test with bad arity
|
||||
self.apiError(master.unregisterService())
|
||||
self.apiError(master.unregisterService(self.caller_id, service))
|
||||
|
||||
# test with bad args
|
||||
self.apiError(master.unregisterService(self.caller_id, '', service_api))
|
||||
self.apiError(master.unregisterService(self.caller_id, service, ''))
|
||||
|
||||
def _testRegisterPublisherInvalid(self):
|
||||
master = self.master
|
||||
|
||||
topic = '/pub_topic'
|
||||
topic_type = 'test_rosmaster/String'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
|
||||
# test with bad arity
|
||||
self.apiError(master.registerPublisher())
|
||||
self.apiError(master.registerPublisher(self.caller_id, topic))
|
||||
self.apiError(master.registerPublisher(self.caller_id, topic, topic_type))
|
||||
|
||||
# test with bad args
|
||||
self.apiError(master.registerPublisher(self.caller_id, '', topic_type, caller_api))
|
||||
self.apiError(master.registerPublisher(self.caller_id, topic, '', caller_api))
|
||||
self.apiError(master.registerPublisher(self.caller_id, topic, topic_type, ''))
|
||||
|
||||
def _testUnregisterPublisherInvalid(self):
|
||||
master = self.master
|
||||
|
||||
topic = '/pub_topic'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
|
||||
# test with bad arity
|
||||
self.apiError(master.unregisterPublisher())
|
||||
self.apiError(master.unregisterPublisher(self.caller_id, topic))
|
||||
|
||||
# test with bad args
|
||||
self.apiError(master.unregisterPublisher(self.caller_id, '', caller_api))
|
||||
self.apiError(master.unregisterPublisher(self.caller_id, topic, ''))
|
||||
|
||||
def _testRegisterSubscriberInvalid(self):
|
||||
master = self.master
|
||||
|
||||
topic = '/sub_topic'
|
||||
topic_type = 'test_rosmaster/String'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
|
||||
# test with bad arity
|
||||
self.apiError(master.registerSubscriber())
|
||||
self.apiError(master.registerSubscriber(self.caller_id, topic))
|
||||
self.apiError(master.registerSubscriber(self.caller_id, topic, topic_type))
|
||||
|
||||
# test with bad args
|
||||
self.apiError(master.registerSubscriber(self.caller_id, '', topic_type, caller_api))
|
||||
self.apiError(master.registerSubscriber(self.caller_id, topic, '', caller_api))
|
||||
self.apiError(master.registerSubscriber(self.caller_id, topic, topic_type, ''))
|
||||
|
||||
def _testUnregisterSubscriberInvalid(self):
|
||||
master = self.master
|
||||
|
||||
topic = '/sub_topic'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
|
||||
# test with bad arity
|
||||
self.apiError(master.registerSubscriber())
|
||||
self.apiError(master.registerSubscriber(self.caller_id, topic))
|
||||
|
||||
# test with bad args
|
||||
self.apiError(master.unregisterSubscriber(self.caller_id, '', caller_api))
|
||||
self.apiError(master.unregisterSubscriber(self.caller_id, topic, ''))
|
||||
|
||||
## common test subroutine of both register and unregister tests. registers the common test cases
|
||||
def _subTestRegisterPublisherSuccess(self):
|
||||
master = self.master
|
||||
|
||||
caller_id = '/pub_node'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
topic_base = '/pub_topic'
|
||||
topic_type = 'test_rosmaster/String'
|
||||
|
||||
# test success
|
||||
for i in range(0, 10):
|
||||
topic_name = "%s-%s"%(topic_base, i)
|
||||
# register the topic
|
||||
self.apiSuccess(master.registerPublisher(caller_id, topic_name, topic_type, caller_api))
|
||||
# test master state
|
||||
# - master knows caller_id
|
||||
val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
|
||||
self.assertEquals(caller_api, val)
|
||||
# - master knows topic type
|
||||
val = self.apiSuccess(master.getPublishedTopics(self.caller_id, '/'))
|
||||
self.assert_([topic_name, topic_type] in val, "master does not know topic type: %s"%val)
|
||||
# - test new api as well
|
||||
val = self.apiSuccess(master.getTopicTypes(self.caller_id))
|
||||
self.assert_([topic_name, topic_type] in val, "master does not know topic type: %s"%val)
|
||||
|
||||
pubs, _, _ = self.apiSuccess(master.getSystemState(self.caller_id))
|
||||
for j in range(0, i+1):
|
||||
jtopic_name = "%s-%s"%(topic_base, j)
|
||||
jentry = [jtopic_name, [caller_id]]
|
||||
self.assert_(jentry in pubs, "master pub/sub list %s is missing %s"%(pubs, jentry))
|
||||
|
||||
# TODO: have to test subscriber callback
|
||||
|
||||
## #591: this test may change if we make registering '*' unsupported
|
||||
def _testRegisterPublisherTypes(self):
|
||||
master = self.master
|
||||
caller_id = '/pub_node'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
topic_name = '/type_test_pub_topic'
|
||||
|
||||
# register anytype first
|
||||
val = self.apiSuccess(master.registerPublisher(caller_id, topic_name, '*', caller_api))
|
||||
self.assertEquals([], val) # should report no subscribers
|
||||
val = self.apiSuccess(master.getPublishedTopics(self.caller_id, '/'))
|
||||
self.assert_([topic_name, '*'] in val, "master is not reporting * as type: %s"%val)
|
||||
# - test new api as well
|
||||
val = self.apiSuccess(master.getTopicTypes(self.caller_id))
|
||||
self.assert_([topic_name, '*'] in val, "master is not reporting * as type: %s"%val)
|
||||
|
||||
# register a grounded type and make sure that '*' can't overwrite it
|
||||
for t in ['test_rosmaster/String', '*']:
|
||||
val = self.apiSuccess(master.registerPublisher(caller_id, topic_name, t, caller_api))
|
||||
self.assertEquals([], val) # should report no subscribers
|
||||
val = self.apiSuccess(master.getPublishedTopics(self.caller_id, '/'))
|
||||
self.assert_([topic_name, 'test_rosmaster/String'] in val, "master is not reporting test_rosmaster/String as type: %s"%val)
|
||||
|
||||
val = self.apiSuccess(master.getTopicTypes(self.caller_id))
|
||||
self.assert_([topic_name, 'test_rosmaster/String'] in val, "master is not reporting test_rosmaster/String as type: %s"%val)
|
||||
|
||||
## validate master.registerPublisher(caller_id, topic, topic_api, caller_api)
|
||||
def _testRegisterPublisherSuccess(self):
|
||||
self._subTestRegisterPublisherSuccess()
|
||||
|
||||
# a couple more test cases to verify that registerPublisher's return value is correct
|
||||
master = self.master
|
||||
topic = '/pub_topic-0'
|
||||
type = 'test_rosmaster/String'
|
||||
pub_caller_api = 'http://localhost:4567/'
|
||||
|
||||
subs = []
|
||||
for i in range(5678, 5685):
|
||||
api = 'http://localhost:%s'%i
|
||||
subs.append(api)
|
||||
self.apiSuccess(master.registerSubscriber('/sub_node-%i'%i, topic, type, api))
|
||||
val = self.apiSuccess(master.registerPublisher('/pub_node', topic, type, pub_caller_api))
|
||||
self.assertEquals(subs, val)
|
||||
|
||||
def _testUnregisterPublisherSuccess(self):
|
||||
self._subTestRegisterPublisherSuccess()
|
||||
master = self.master
|
||||
caller_id = '/pub_node'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
topic_base = '/pub_topic'
|
||||
|
||||
for i in range(0, 10):
|
||||
topic_name = "%s-%s"%(topic_base, i)
|
||||
|
||||
# unregister the topic
|
||||
code, msg, val = master.unregisterPublisher(caller_id, topic_name, caller_api)
|
||||
self.assertEquals(code, 1, "code != 1, return message was [%s]"%msg)
|
||||
|
||||
# test the master state
|
||||
if i < 9:
|
||||
val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
|
||||
self.assertEquals(caller_api, val, "master prematurely invalidated node entry for [%s] (lookupNode)"%caller_id)
|
||||
|
||||
pubs, _, _ = self.apiSuccess(master.getSystemState(self.caller_id))
|
||||
for j in range(0, i+1):
|
||||
jtopic_name = "%s-%s"%(topic_base, j)
|
||||
jentry = [jtopic_name, [caller_id]]
|
||||
self.assert_(jentry not in pubs, "master pub/sub list %s should not have %s"%(pubs, jentry))
|
||||
for j in range(i+1, 10):
|
||||
jtopic_name = "%s-%s"%(topic_base, j)
|
||||
jentry = [jtopic_name, [caller_id]]
|
||||
self.assert_(jentry in pubs, "master pub/sub list %s is missing %s"%(pubs, jentry))
|
||||
|
||||
# TODO: have to test subscriber callback
|
||||
|
||||
# - #457 make sure that lookupNode isn't returning stale info
|
||||
self.apiError(master.lookupNode(self.caller_id, caller_id), "master has a stale reference to unregistered topic node API. pubs are %s"%pubs)
|
||||
|
||||
## common test subroutine of both register and unregister tests. registers the common test cases
|
||||
## 'simple' test cases do not setup any publisher state to validate against
|
||||
def _subTestRegisterSubscriberSimpleSuccess(self):
|
||||
master = self.master
|
||||
|
||||
caller_id = '/sub_node'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
topic_base = '/sub_topic'
|
||||
topic_type = 'test_rosmaster/String'
|
||||
|
||||
# test success
|
||||
for i in range(0, 10):
|
||||
topic_name = "%s-%s"%(topic_base, i)
|
||||
# register the topic
|
||||
self.apiSuccess(master.registerSubscriber(caller_id, topic_name, topic_type, caller_api))
|
||||
# test master state
|
||||
# - master knows caller_id
|
||||
val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
|
||||
self.assertEquals(caller_api, val)
|
||||
|
||||
# - master should know topic type
|
||||
val = self.apiSuccess(master.getTopicTypes(self.caller_id))
|
||||
self.assert_([topic_name, topic_type] in val, "master does not know topic type: %s"%val)
|
||||
|
||||
_, subs, _ = self.apiSuccess(master.getSystemState(self.caller_id))
|
||||
for j in range(0, i+1):
|
||||
jtopic_name = "%s-%s"%(topic_base, j)
|
||||
jentry = [jtopic_name, [caller_id]]
|
||||
self.assert_(jentry in subs, "master pub/sub list %s is missing %s"%(subs, jentry))
|
||||
|
||||
## validate master.registerSubscriber(caller_id, topic, topic_api, caller_api)
|
||||
def _testRegisterSubscriberSimpleSuccess(self):
|
||||
self._subTestRegisterSubscriberSimpleSuccess()
|
||||
|
||||
def _testUnregisterSubscriberSuccess(self):
|
||||
self._subTestRegisterSubscriberSimpleSuccess()
|
||||
master = self.master
|
||||
caller_id = '/sub_node'
|
||||
caller_api = 'http://localhost:4567/'
|
||||
topic_base = '/sub_topic'
|
||||
|
||||
for i in range(0, 10):
|
||||
topic_name = "%s-%s"%(topic_base, i)
|
||||
|
||||
# unregister the topic
|
||||
code, msg, val = master.unregisterSubscriber(caller_id, topic_name, caller_api)
|
||||
self.assertEquals(code, 1, "code != 1, return message was [%s]"%msg)
|
||||
|
||||
# test the master state
|
||||
if i < 9:
|
||||
val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
|
||||
self.assertEquals(caller_api, val, "master prematurely invalidated node entry for [%s] (lookupNode)"%caller_id)
|
||||
|
||||
_, subs, _ = self.apiSuccess(master.getSystemState(self.caller_id))
|
||||
for j in range(0, i+1):
|
||||
jtopic_name = "%s-%s"%(topic_base, j)
|
||||
jentry = [jtopic_name, [caller_id]]
|
||||
self.assert_(jentry not in subs, "master pub/sub list %s should not have %s"%(subs, jentry))
|
||||
for j in range(i+1, 10):
|
||||
jtopic_name = "%s-%s"%(topic_base, j)
|
||||
jentry = [jtopic_name, [caller_id]]
|
||||
self.assert_(jentry in subs, "master pub/sub list %s is missing %s"%(subs, jentry))
|
||||
|
||||
# - #457 make sure that lookupNode isn't returning stale info
|
||||
self.apiError(master.lookupNode(self.caller_id, caller_id), "master has a stale reference to unregistered topic node API. subs are %s"%subs)
|
||||
|
||||
|
||||
365
thirdparty/ros/ros_comm/test/test_rosmaster/test/node.py
vendored
Normal file
365
thirdparty/ros/ros_comm/test/test_rosmaster/test/node.py
vendored
Normal file
@@ -0,0 +1,365 @@
|
||||
# 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: testSlave.py 1100 2008-05-29 20:23:54Z sfkwc $
|
||||
|
||||
import os
|
||||
import sys
|
||||
import string
|
||||
import time
|
||||
try:
|
||||
from xmlrpc.client import ServerProxy
|
||||
except ImportError:
|
||||
from xmlrpclib import ServerProxy
|
||||
|
||||
import rospy
|
||||
import rosgraph
|
||||
|
||||
from rosclient import *
|
||||
|
||||
NODE_INTEGRATION_NAME = "node_integration_test"
|
||||
|
||||
|
||||
_required_subscriptions = 'test_string_in', 'test_primitives_in', 'test_arrays_in', 'test_header_in', 'probe_topic'
|
||||
|
||||
# only publishers determine topic type, so we test against their declared spec
|
||||
_required_publications_map = {
|
||||
'test_string_out': 'test_rosmaster/TestString',
|
||||
'test_primitives_out': 'test_rosmaster/TestPrimitives',
|
||||
'test_arrays_out': 'test_rosmaster/TestArrays',
|
||||
'test_header_out': 'test_rosmaster/TestHeader',
|
||||
}
|
||||
_required_publications = _required_publications_map.keys()
|
||||
|
||||
_TCPROS = 'TCPROS'
|
||||
|
||||
# NOTE: probe_topic is a unpublished topic that merely exists to test
|
||||
# APIs that talk about subscriptions (e.g. publisherUpdate)
|
||||
|
||||
_name = None
|
||||
## set_node_name() must be called prior to the unit test so that the test harness knows its
|
||||
## ROS name.
|
||||
def set_node_name(name):
|
||||
global _name
|
||||
_name = name
|
||||
|
||||
# Have to try as hard as possible to not use rospy code in testing rospy code, so this is
|
||||
# a reimplementation of the caller ID spec so that NodeApiTestCase knows its name
|
||||
## reimplementation of caller ID spec separately from rospy
|
||||
def get_caller_id():
|
||||
if _name is None:
|
||||
raise Exception("set_node_name has not been called yet")
|
||||
ros_ns = os.environ.get(rosgraph.ROS_NAMESPACE, rosgraph.names.GLOBALNS)
|
||||
return rosgraph.names.ns_join(ros_ns, _name)
|
||||
|
||||
## Parent of node API and integration test cases. Performs common state setup
|
||||
class _NodeTestCase(TestRosClient):
|
||||
|
||||
def __init__(self, *args):
|
||||
super(_NodeTestCase, self).__init__(*args)
|
||||
|
||||
self.ns = os.environ.get(rosgraph.ROS_NAMESPACE, rosgraph.names.GLOBALNS)
|
||||
self.caller_id = get_caller_id()
|
||||
|
||||
# load in name of test node
|
||||
self.test_node = 'test_node' #default
|
||||
for arg in sys.argv:
|
||||
if arg.startswith("--node="):
|
||||
self.test_node = arg[len("--node="):]
|
||||
# resolve
|
||||
self.test_node = rosgraph.names.ns_join(self.ns, self.test_node)
|
||||
|
||||
|
||||
def setUp(self):
|
||||
super(_NodeTestCase, self).setUp()
|
||||
# retrieve handle on node
|
||||
# give ourselves five seconds for node to appear
|
||||
import time
|
||||
timeout_t = 5.0 + time.time()
|
||||
self.node_api = None
|
||||
while time.time() < timeout_t and not self.node_api:
|
||||
code, msg, node_api = self.master.lookupNode(self.caller_id, self.test_node)
|
||||
if code == 1:
|
||||
self.node_api = node_api
|
||||
if not self.node_api:
|
||||
self.fail("master did not return XML-RPC API for [%s, %s]"%(self.caller_id, self.test_node))
|
||||
print("[%s] API = %s" %(self.test_node, self.node_api))
|
||||
self.assert_(self.node_api.startswith('http'))
|
||||
self.node = ServerProxy(self.node_api)
|
||||
|
||||
## validates a URI as being http(s)
|
||||
def _checkUri(self, uri):
|
||||
try:
|
||||
from urllib.parse import urlparse
|
||||
except ImportError:
|
||||
from urlparse import urlparse
|
||||
parsed = urlparse(uri)
|
||||
self.assert_(parsed[0] in ['http', 'https'], 'protocol [%s] in [%s] invalid'%(parsed[0], uri))
|
||||
self.assert_(parsed[1], 'host missing [%s]'%uri)
|
||||
if not sys.version.startswith('2.4'): #check not available on py24
|
||||
self.assert_(parsed.port, 'port missing/invalid [%s]'%uri)
|
||||
|
||||
## dynamically create the expected topic->type map based on the current name resolution context
|
||||
def _createTopicTypeMap(self):
|
||||
new_map = {}
|
||||
for t in _required_publications_map.keys():
|
||||
new_map[rospy.resolve_name(t)] = _required_publications_map[t]
|
||||
return new_map
|
||||
|
||||
## Expects a single test node to be running with name 'test_node' and subscribed to 'test_string'
|
||||
class NodeApiTestCase(_NodeTestCase):
|
||||
|
||||
## validate node.getPid(caller_id)
|
||||
def testGetPid(self):
|
||||
# test with bad arity
|
||||
self.apiError(self.node.getPid())
|
||||
# test success
|
||||
pid = self.apiSuccess(self.node.getPid(self.caller_id))
|
||||
self.assert_(pid > 0)
|
||||
|
||||
## subroutine for testGetSubscriptions/testGetPublications
|
||||
def _checkTopics(self, required, actual):
|
||||
actual = [t for t, _ in actual]
|
||||
missing = set(required) - set(actual)
|
||||
self.failIf(len(missing), 'missing required topics: %s'%(','.join(missing)))
|
||||
|
||||
## validate node.getPublications(caller_id)
|
||||
def testGetPublications(self):
|
||||
# test with bad arity
|
||||
self.apiError(self.node.getPublications())
|
||||
self.apiError(self.node.getPublications(self.caller_id, 'something extra'))
|
||||
|
||||
# test success
|
||||
self._checkTopics([rospy.resolve_name(t) for t in _required_publications],
|
||||
self.apiSuccess(self.node.getPublications(self.caller_id)))
|
||||
## validate node.getSubscriptions(caller_id)
|
||||
def testGetSubscriptions(self):
|
||||
# test with bad arity
|
||||
self.apiError(self.node.getSubscriptions())
|
||||
self.apiError(self.node.getSubscriptions(self.caller_id, 'something extra'))
|
||||
# test success
|
||||
self._checkTopics([rospy.resolve_name(t) for t in _required_subscriptions],
|
||||
self.apiSuccess(self.node.getSubscriptions(self.caller_id)))
|
||||
|
||||
## validate node.paramUpdate(caller_id, key, value)
|
||||
def testParamUpdate(self):
|
||||
node = self.node
|
||||
good_key = rosgraph.names.ns_join(self.ns, 'good_key')
|
||||
bad_key = rosgraph.names.ns_join(self.ns, 'bad_key')
|
||||
|
||||
# test bad key
|
||||
self.apiError(node.paramUpdate(self.caller_id, '', 'bad'))
|
||||
self.apiError(node.paramUpdate(self.caller_id, 'no_namespace', 'bad'))
|
||||
# test with bad arity
|
||||
self.apiError(node.paramUpdate(self.caller_id, bad_key))
|
||||
self.apiError(node.paramUpdate(self.caller_id))
|
||||
|
||||
# node is not subscribed to good_key (yet)
|
||||
self.apiError(node.paramUpdate(self.caller_id, good_key, 'good_value'))
|
||||
|
||||
# we can't actually test success cases without forcing node to subscribe
|
||||
#self.apiSuccess(node.paramUpdate(self.caller_id, good_key, 1))
|
||||
#self.apiSuccess(node.paramUpdate(self.caller_id, good_key, True))
|
||||
#self.apiSuccess(node.paramUpdate(self.caller_id, good_key, 10.0))
|
||||
|
||||
## validate node.getUri(caller_id)
|
||||
def testGetUri(self):
|
||||
# test bad arity
|
||||
self.apiError(self.node.getUri(self.caller_id, 'bad'))
|
||||
self.apiError(self.node.getUri())
|
||||
# test success
|
||||
self._checkUri(self.apiSuccess(self.node.getUri(self.caller_id)))
|
||||
|
||||
## validate node.getName(caller_id)
|
||||
def testGetName(self):
|
||||
# test bad arity
|
||||
self.apiError(self.node.getName(self.caller_id, 'bad'))
|
||||
self.apiError(self.node.getName())
|
||||
# test success
|
||||
val = self.apiSuccess(self.node.getName(self.caller_id))
|
||||
self.assert_(len(val), "empty name")
|
||||
|
||||
## validate node.getMasterUri(caller_id)
|
||||
def testGetMasterUri(self):
|
||||
# test bad arity
|
||||
self.apiError(self.node.getMasterUri(self.caller_id, 'bad'))
|
||||
self.apiError(self.node.getMasterUri())
|
||||
# test success
|
||||
uri = self.apiSuccess(self.node.getMasterUri(self.caller_id))
|
||||
self._checkUri(uri)
|
||||
self.assertEquals(rosgraph.get_master_uri(), uri)
|
||||
|
||||
## validate node.publisherUpdate(caller_id, topic, uris)
|
||||
def testPublisherUpdate(self):
|
||||
node = self.node
|
||||
probe_topic = rosgraph.names.ns_join(self.ns, 'probe_topic')
|
||||
fake_topic = rosgraph.names.ns_join(self.ns, 'fake_topic')
|
||||
# test bad arity
|
||||
self.apiError(node.getBusStats(self.caller_id, 'bad'))
|
||||
self.apiError(node.getBusStats())
|
||||
# test bad args
|
||||
self.apiError(node.publisherUpdate(self.caller_id, '/bad_topic', 'bad'))
|
||||
self.apiError(node.publisherUpdate(self.caller_id, '/bad_topic', 2))
|
||||
self.apiError(node.publisherUpdate(self.caller_id, '/bad_topic', False))
|
||||
self.apiError(node.publisherUpdate(self.caller_id, '/bad_topic', ['bad']))
|
||||
self.apiError(node.publisherUpdate())
|
||||
|
||||
# test success
|
||||
# still success even if not actually interested in topic
|
||||
self.apiSuccess(node.publisherUpdate(self.caller_id, fake_topic,
|
||||
['http://localhost:1234', 'http://localhost:5678']))
|
||||
self.apiSuccess(node.publisherUpdate(self.caller_id, fake_topic,
|
||||
[]))
|
||||
# try it with it the /probe_topic, which will exercise some error branches in the client
|
||||
self.apiSuccess(node.publisherUpdate(self.caller_id, probe_topic,
|
||||
['http://unroutablefakeservice:1234']))
|
||||
# give it some time to make sure it's attempted contact
|
||||
time.sleep(1.0)
|
||||
# check that it's still there
|
||||
self.apiSuccess(node.publisherUpdate(self.caller_id, probe_topic,
|
||||
[]))
|
||||
|
||||
def _checkTCPROS(self, protocol_params):
|
||||
self.assert_(protocol_params, "no protocol params returned")
|
||||
self.assert_(type(protocol_params) == list, "protocol params must be a list: %s"%protocol_params)
|
||||
self.assertEquals(3, len(protocol_params), "TCPROS params should have length 3: %s"%protocol_params)
|
||||
self.assertEquals(protocol_params[0], _TCPROS)
|
||||
# expect ['TCPROS', 1.2.3.4, 1234]
|
||||
self.assertEquals(protocol_params[0], _TCPROS)
|
||||
|
||||
def testRequestTopic(self):
|
||||
node = self.node
|
||||
protocols = [[_TCPROS]]
|
||||
probe_topic = rosgraph.names.ns_join(self.ns, 'probe_topic')
|
||||
fake_topic = rosgraph.names.ns_join(self.ns, 'fake_topic')
|
||||
|
||||
# test bad arity
|
||||
self.apiError(node.requestTopic(self.caller_id, probe_topic, protocols, 'extra stuff'))
|
||||
self.apiError(node.requestTopic(self.caller_id, probe_topic))
|
||||
self.apiError(node.requestTopic(self.caller_id))
|
||||
self.apiError(node.requestTopic())
|
||||
# test bad args
|
||||
self.apiError(node.requestTopic(self.caller_id, 1, protocols))
|
||||
self.apiError(node.requestTopic(self.caller_id, '', protocols))
|
||||
self.apiError(node.requestTopic(self.caller_id, fake_topic, protocols))
|
||||
self.apiError(node.requestTopic(self.caller_id, probe_topic, 'fake-protocols'))
|
||||
|
||||
topics = [rosgraph.names.ns_join(self.ns, t) for t in _required_publications]
|
||||
# currently only support TCPROS as we require all clients to support this
|
||||
protocols = [[_TCPROS]]
|
||||
for topic in topics:
|
||||
self._checkTCPROS(self.apiSuccess(node.requestTopic(self.caller_id, topic, protocols)))
|
||||
protocols = [['FakeTransport', 1234, 5678], [_TCPROS], ['AnotherFakeTransport']]
|
||||
# try each one more time, this time with more protocol choices
|
||||
for topic in topics:
|
||||
self._checkTCPROS(self.apiSuccess(node.requestTopic(self.caller_id, topic, protocols)))
|
||||
|
||||
def testGetBusInfo(self):
|
||||
# test bad arity
|
||||
self.apiError(self.node.getBusInfo(self.caller_id, 'bad'))
|
||||
self.apiError(self.node.getBusInfo())
|
||||
#TODO: finish
|
||||
|
||||
def testGetBusStats(self):
|
||||
# test bad arity
|
||||
self.apiError(self.node.getBusStats(self.caller_id, 'bad'))
|
||||
self.apiError(self.node.getBusStats())
|
||||
#TODO: finish
|
||||
|
||||
## test the state of the master based on expected node registration
|
||||
def testRegistrations(self):
|
||||
# setUp() ensures the node has registered with the master
|
||||
topics = self.apiSuccess(self.master.getPublishedTopics(self.caller_id, ''))
|
||||
topic_names = [t for t, type in topics]
|
||||
required_topic_pubs = [rospy.resolve_name(t) for t in _required_publications]
|
||||
required_topic_subs = [rospy.resolve_name(t) for t in _required_subscriptions]
|
||||
self._checkTopics(required_topic_pubs, topics)
|
||||
|
||||
# now check types
|
||||
topicTypeMap = self._createTopicTypeMap()
|
||||
for topic, type in topics:
|
||||
if topic in topicTypeMap:
|
||||
self.assertEquals(type, topicTypeMap[topic], "topic [%s]: type [%s] does not match expected [%s]"%(type, topic, topicTypeMap[topic]))
|
||||
|
||||
# now check actual URIs
|
||||
node_name = self.test_node
|
||||
systemState = self.apiSuccess(self.master.getSystemState(self.caller_id))
|
||||
pubs, subs, srvs = systemState
|
||||
for topic, list in pubs:
|
||||
if topic in required_topic_pubs:
|
||||
self.assert_(node_name in list, "%s not in %s"%(self.node_api, list))
|
||||
for topic, list in subs:
|
||||
if topic in required_topic_subs:
|
||||
self.assert_(node_name in list, "%s not in %s"%(self.node_api, list))
|
||||
for service, list in srvs:
|
||||
#TODO: no service tests yet
|
||||
pass
|
||||
|
||||
|
||||
## Performs end-to-end integration tests of a test_node. NodeIntegrationTestCase
|
||||
## itself is a rospy node and thus implicitly depends on rospy functionality.
|
||||
class NodeIntegrationTestCase(_NodeTestCase):
|
||||
|
||||
def __init__(self, *args):
|
||||
super(NodeIntegrationTestCase, self).__init__(*args)
|
||||
rospy.init_node(NODE_INTEGRATION_NAME)
|
||||
|
||||
def testString(self):
|
||||
pub = rospy.Publisher('test_string_in', test_rosmaster.msg.String)
|
||||
sub = rospy.Subscriber('test_string_in', test_rosmaster.msg.String)
|
||||
#TODO: publish a bunch and check sequencing + caller_id
|
||||
pub.unregister()
|
||||
sub.unregister()
|
||||
|
||||
def testPrimitives(self):
|
||||
pub = rospy.Publisher('test_primitives_in', test_rosmaster.msg.String)
|
||||
sub = rospy.Subscriber('test_primitives_out', test_rosmaster.msg.String)
|
||||
#TODO: publish a bunch and check sequencing + caller_id
|
||||
pub.unregister()
|
||||
sub.unregister()
|
||||
|
||||
def testArrays(self):
|
||||
pub = rospy.Publisher('test_header_in', test_rosmaster.msg.String)
|
||||
sub = rospy.Subscriber('test_header_out', test_rosmaster.msg.String)
|
||||
#TODO: publish a bunch and check sequencing + caller_id
|
||||
pub.unregister()
|
||||
sub.unregister()
|
||||
|
||||
def testHeader(self):
|
||||
#msg.auto_header = True
|
||||
pub = rospy.Publisher('test_header_in', test_rosmaster.msg.String)
|
||||
sub = rospy.Subscriber('test_header_out', test_rosmaster.msg.String)
|
||||
#TODO: publish a bunch and check sequencing + caller_id
|
||||
pub.unregister()
|
||||
sub.unregister()
|
||||
|
||||
|
||||
101
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/add_two_ints_client
vendored
Executable file
101
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/add_two_ints_client
vendored
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/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.
|
||||
|
||||
## Simple demo of a rospy service client that calls a service to add
|
||||
## two integers.
|
||||
|
||||
PKG = 'test_rosmaster' # this package name
|
||||
|
||||
import sys
|
||||
import os
|
||||
import string
|
||||
|
||||
import rospy
|
||||
|
||||
# imports the AddTwoInts service
|
||||
from test_rosmaster.srv import *
|
||||
|
||||
## add two numbers using the add_two_ints service
|
||||
## @param x int: first number to add
|
||||
## @param y int: second number to add
|
||||
def add_two_ints_client(x, y):
|
||||
|
||||
# NOTE: you don't have to call rospy.init_node() to make calls against
|
||||
# a service. This is because service clients do not have to be
|
||||
# nodes.
|
||||
|
||||
# block until the add_two_ints service is available
|
||||
# you can optionally specify a timeout
|
||||
rospy.wait_for_service('add_two_ints')
|
||||
|
||||
try:
|
||||
# create a handle to the add_two_ints service
|
||||
add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts)
|
||||
|
||||
print "Requesting %s+%s"%(x, y)
|
||||
|
||||
# simplified style
|
||||
resp1 = add_two_ints(x, y)
|
||||
|
||||
# formal style
|
||||
resp2 = add_two_ints.call(AddTwoIntsRequest(x, y))
|
||||
|
||||
if not resp1.sum == (x + y):
|
||||
raise Exception("test failure, returned sum was %s"%resp1.sum)
|
||||
if not resp2.sum == (x + y):
|
||||
raise Exception("test failure, returned sum was %s"%resp2.sum)
|
||||
return resp1.sum
|
||||
except rospy.ServiceException as e:
|
||||
print "Service call failed: %s"%e
|
||||
|
||||
def usage():
|
||||
return "%s [x y]"%sys.argv[0]
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
argv = rospy.myargv()
|
||||
if len(argv) == 1:
|
||||
import random
|
||||
x = random.randint(-50000, 50000)
|
||||
y = random.randint(-50000, 50000)
|
||||
elif len(argv) == 3:
|
||||
try:
|
||||
x = string.atoi(argv[1])
|
||||
y = string.atoi(argv[2])
|
||||
except:
|
||||
print usage()
|
||||
sys.exit(1)
|
||||
else:
|
||||
print usage()
|
||||
sys.exit(1)
|
||||
print "%s + %s = %s"%(x, y, add_two_ints_client(x, y))
|
||||
57
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/add_two_ints_server
vendored
Executable file
57
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/add_two_ints_server
vendored
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/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: add_two_ints_server 3804 2009-02-11 02:16:00Z rob_wheeler $
|
||||
|
||||
## Simple demo of a rospy service that add two integers
|
||||
|
||||
PKG = 'test_rosmaster' # this package name
|
||||
NAME = 'add_two_ints_server'
|
||||
|
||||
# import the AddTwoInts service
|
||||
from test_rosmaster.srv import *
|
||||
import rospy
|
||||
|
||||
def add_two_ints(req):
|
||||
print("Returning [%s + %s = %s]" % (req.a, req.b, (req.a + req.b)))
|
||||
return AddTwoIntsResponse(req.a + req.b)
|
||||
|
||||
def add_two_ints_server():
|
||||
rospy.init_node(NAME)
|
||||
s = rospy.Service('add_two_ints', AddTwoInts, add_two_ints)
|
||||
|
||||
# spin() keeps Python from exiting until node is shutdown
|
||||
rospy.spin()
|
||||
|
||||
if __name__ == "__main__":
|
||||
add_two_ints_server()
|
||||
57
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/fail_two_ints_server
vendored
Executable file
57
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/fail_two_ints_server
vendored
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/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.
|
||||
|
||||
## variant of add two ints that fails if the first argument is -1
|
||||
|
||||
PKG = 'test_rosmaster' # this package name
|
||||
NAME = 'add_two_ints_server'
|
||||
|
||||
# import the AddTwoInts service
|
||||
from test_rosmaster.srv import *
|
||||
import rospy
|
||||
|
||||
def add_two_ints(req):
|
||||
if req.a == -1:
|
||||
raise rospy.ServiceException("intentional failure")
|
||||
print("Returning [%s + %s = %s]" % (req.a, req.b, (req.a + req.b)))
|
||||
return {'sum': req.a + req.b}
|
||||
|
||||
def add_two_ints_server():
|
||||
rospy.init_node(NAME)
|
||||
s = rospy.Service('add_two_ints', AddTwoInts, add_two_ints)
|
||||
|
||||
# spin() keeps Python from exiting until node is shutdown
|
||||
rospy.spin()
|
||||
|
||||
if __name__ == "__main__":
|
||||
add_two_ints_server()
|
||||
59
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/fake_time.py
vendored
Executable file
59
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/fake_time.py
vendored
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python
|
||||
# Software License Agreement (BSD License)
|
||||
#
|
||||
# Copyright (c) 2010, 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.
|
||||
|
||||
"""
|
||||
This publishes wall clock to the /clock topic to test simulated time routines
|
||||
"""
|
||||
|
||||
import time
|
||||
import rospy
|
||||
from rosgraph_msgs.msg import Clock
|
||||
|
||||
def faketime():
|
||||
rospy.set_param('/use_sim_time', True)
|
||||
pub = rospy.Publisher('/clock', Clock)
|
||||
rospy.init_node('fake_time')
|
||||
c = Clock()
|
||||
while not rospy.is_shutdown():
|
||||
float_secs = time.time()
|
||||
secs = int(float_secs)
|
||||
c.clock.nsecs = int((float_secs - secs) * 1000000000)
|
||||
c.clock.secs = secs
|
||||
pub.publish(c)
|
||||
time.sleep(0.01)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
faketime()
|
||||
except rospy.ROSInterruptException: pass
|
||||
|
||||
47
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/testAllCommonFlows
vendored
Executable file
47
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/testAllCommonFlows
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
PKG = 'test_ros'
|
||||
MODULE = 'test_ros.testAllCommonFlows' #this is the module that will be invoked by python
|
||||
|
||||
######################################################
|
||||
# BOILERPLATE: Should not have to modify anything
|
||||
# below except for very last line
|
||||
######################################################
|
||||
# Bootstrap ourselves into latest rospy install
|
||||
import sys, os
|
||||
BOOTSTRAP_VERSION = "0.1"
|
||||
|
||||
# Read in ROS_ROOT
|
||||
if not os.environ.has_key('ROS_ROOT'):
|
||||
print """\nCannot run ROS: ROS_ROOT is not set.\nPlease set the ROS_ROOT environment variable to the
|
||||
location of your ROS install.\n"""
|
||||
sys.exit(-1)
|
||||
rosRoot = os.environ['ROS_ROOT']
|
||||
|
||||
# Read in the rospy directory location from the 'rospack latest rospy' command
|
||||
rospackLatest = os.popen(os.path.join(rosRoot,'rospack')+' latest rospy', 'r')
|
||||
rospyDir = rospackLatest.read()
|
||||
rospackLatest.close()
|
||||
if rospyDir is None or not os.path.isdir(rospyDir.strip()):
|
||||
print "\nERROR: Cannot locate rospy installation.\n"
|
||||
sys.exit(-1)
|
||||
|
||||
# Run launcher bootstrapper
|
||||
sys.path.append(os.path.join(rospyDir.strip(),'scripts'))
|
||||
import launcher
|
||||
|
||||
manifestFile = launcher.getManifestFile(sys.argv[0], PKG)
|
||||
launcher.init(BOOTSTRAP_VERSION)
|
||||
launchCommand, launchArgs, launchEnv = \
|
||||
launcher.getLaunchCommands(manifestFile, MODULE)
|
||||
launcher.ready(launchCommand, launchArgs, launchEnv, BOOTSTRAP_VERSION)
|
||||
|
||||
######################################################
|
||||
# END BOILERPLATE:
|
||||
# You may wish to modify the exec command below to
|
||||
# customize the behavior of your node, e.g.:
|
||||
# * env['FOO'] = bar
|
||||
# * launchArgs.append('--test')
|
||||
######################################################
|
||||
|
||||
os.execvpe(launchCommand, launchArgs, launchEnv)
|
||||
47
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/testMaster
vendored
Executable file
47
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/testMaster
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
PKG = 'test_ros'
|
||||
MODULE = 'test_ros.testMaster' #this is the module that will be invoked by python
|
||||
|
||||
######################################################
|
||||
# BOILERPLATE: Should not have to modify anything
|
||||
# below except for very last line
|
||||
######################################################
|
||||
# Bootstrap ourselves into latest rospy install
|
||||
import sys, os
|
||||
BOOTSTRAP_VERSION = "0.1"
|
||||
|
||||
# Read in ROS_ROOT
|
||||
if not os.environ.has_key('ROS_ROOT'):
|
||||
print """\nCannot run ROS: ROS_ROOT is not set.\nPlease set the ROS_ROOT environment variable to the
|
||||
location of your ROS install.\n"""
|
||||
sys.exit(-1)
|
||||
rosRoot = os.environ['ROS_ROOT']
|
||||
|
||||
# Read in the rospy directory location from the 'rospack latest rospy' command
|
||||
rospackLatest = os.popen(os.path.join(rosRoot,'rospack')+' latest rospy', 'r')
|
||||
rospyDir = rospackLatest.read()
|
||||
rospackLatest.close()
|
||||
if rospyDir is None or not os.path.isdir(rospyDir.strip()):
|
||||
print "\nERROR: Cannot locate rospy installation.\n"
|
||||
sys.exit(-1)
|
||||
|
||||
# Run launcher bootstrapper
|
||||
sys.path.append(os.path.join(rospyDir.strip(),'scripts'))
|
||||
import launcher
|
||||
|
||||
manifestFile = launcher.getManifestFile(sys.argv[0], PKG)
|
||||
launcher.init(BOOTSTRAP_VERSION)
|
||||
launchCommand, launchArgs, launchEnv = \
|
||||
launcher.getLaunchCommands(manifestFile, MODULE)
|
||||
launcher.ready(launchCommand, launchArgs, launchEnv, BOOTSTRAP_VERSION)
|
||||
|
||||
######################################################
|
||||
# END BOILERPLATE:
|
||||
# You may wish to modify the exec command below to
|
||||
# customize the behavior of your node, e.g.:
|
||||
# * env['FOO'] = bar
|
||||
# * launchArgs.append('--test')
|
||||
######################################################
|
||||
|
||||
os.execvpe(launchCommand, launchArgs, launchEnv)
|
||||
47
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/testSlave
vendored
Executable file
47
thirdparty/ros/ros_comm/test/test_rosmaster/test/nodes/testSlave
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
PKG = 'test_ros'
|
||||
MODULE = 'test_ros.testSlave' #this is the module that will be invoked by python
|
||||
|
||||
######################################################
|
||||
# BOILERPLATE: Should not have to modify anything
|
||||
# below except for very last line
|
||||
######################################################
|
||||
# Bootstrap ourselves into latest rospy install
|
||||
import sys, os
|
||||
BOOTSTRAP_VERSION = "0.1"
|
||||
|
||||
# Read in ROS_ROOT
|
||||
if not os.environ.has_key('ROS_ROOT'):
|
||||
print """\nCannot run ROS: ROS_ROOT is not set.\nPlease set the ROS_ROOT environment variable to the
|
||||
location of your ROS install.\n"""
|
||||
sys.exit(-1)
|
||||
rosRoot = os.environ['ROS_ROOT']
|
||||
|
||||
# Read in the rospy directory location from the 'rospack latest rospy' command
|
||||
rospackLatest = os.popen(os.path.join(rosRoot,'rospack')+' latest rospy', 'r')
|
||||
rospyDir = rospackLatest.read()
|
||||
rospackLatest.close()
|
||||
if rospyDir is None or not os.path.isdir(rospyDir.strip()):
|
||||
print "\nERROR: Cannot locate rospy installation.\n"
|
||||
sys.exit(-1)
|
||||
|
||||
# Run launcher bootstrapper
|
||||
sys.path.append(os.path.join(rospyDir.strip(),'scripts'))
|
||||
import launcher
|
||||
|
||||
manifestFile = launcher.getManifestFile(sys.argv[0], PKG)
|
||||
launcher.init(BOOTSTRAP_VERSION)
|
||||
launchCommand, launchArgs, launchEnv = \
|
||||
launcher.getLaunchCommands(manifestFile, MODULE)
|
||||
launcher.ready(launchCommand, launchArgs, launchEnv, BOOTSTRAP_VERSION)
|
||||
|
||||
######################################################
|
||||
# END BOILERPLATE:
|
||||
# You may wish to modify the exec command below to
|
||||
# customize the behavior of your node, e.g.:
|
||||
# * env['FOO'] = bar
|
||||
# * launchArgs.append('--test')
|
||||
######################################################
|
||||
|
||||
os.execvpe(launchCommand, launchArgs, launchEnv)
|
||||
588
thirdparty/ros/ros_comm/test/test_rosmaster/test/param_server_test_case.py
vendored
Normal file
588
thirdparty/ros/ros_comm/test/test_rosmaster/test/param_server_test_case.py
vendored
Normal file
@@ -0,0 +1,588 @@
|
||||
#!/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: test_embed_msg.py 1986 2008-08-26 23:57:56Z sfkwc $
|
||||
|
||||
## Integration test for empty services to test serializers
|
||||
## and transport
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
try:
|
||||
from xmlrpc.client import DateTime
|
||||
except ImportError:
|
||||
from xmlrpclib import DateTime
|
||||
import math
|
||||
import datetime
|
||||
import random
|
||||
import traceback
|
||||
|
||||
import rostest
|
||||
from roslib.names import make_global_ns, ns_join
|
||||
|
||||
from rosclient import TestRosClient
|
||||
|
||||
HAS_PARAM = True
|
||||
|
||||
## Parameter Server API Test Cases. These tests are individually
|
||||
## enabled by param server test nodes. Each test assumes a fresh param
|
||||
## server, so we cannot run within the same roslaunch/rostest session.
|
||||
class ParamServerTestCase(TestRosClient):
|
||||
|
||||
def _setParam(self, ctx, myState, testVals, master):
|
||||
ctx = make_global_ns(ctx)
|
||||
for type, vals in testVals:
|
||||
try:
|
||||
callerId = ns_join(ctx, "node")
|
||||
count = 0
|
||||
for val in vals:
|
||||
key = "%s-%s"%(type,count)
|
||||
#print("master.setParam(%s,%s)"%(callerId, key))
|
||||
master.setParam(callerId, key, val)
|
||||
self.assert_(self.apiSuccess(master.hasParam(callerId, key)))
|
||||
trueKey = ns_join(ctx, key)
|
||||
myState[trueKey] = val
|
||||
count += 1
|
||||
except Exception:
|
||||
assert "getParam failed on type[%s], val[%s]"%(type,val)
|
||||
#self._checkParamState(myState)
|
||||
|
||||
def _checkParamState(self, myState):
|
||||
master = self.master
|
||||
callerId = 'master' #validate from root
|
||||
for (k, v) in myState.items():
|
||||
assert self.apiSuccess(master.hasParam(callerId, k))
|
||||
#print("verifying parameter %s"%k)
|
||||
try:
|
||||
v2 = self.apiSuccess(master.getParam(callerId, k))
|
||||
except:
|
||||
raise Exception("Exception raised while calling master.getParam(%s,%s): %s"%(callerId, k, traceback.format_exc()))
|
||||
if isinstance(v2, DateTime):
|
||||
self.assertEquals(DateTime(v), v2, "[%s]: %s != %s, %s"%(k, v, v2, v2.__class__))
|
||||
elif type(v2) == float:
|
||||
self.assertAlmostEqual(v, v2, 3, "[%s]: %s != %s, %s"%(k, v, v2, v2.__class__))
|
||||
else:
|
||||
self.assertEquals(v, v2)
|
||||
paramNames = myState.keys()
|
||||
remoteParamNames = self.apiSuccess(master.getParamNames(callerId))
|
||||
# filter out the roslaunch params like run id and roslaunch/, which are always set
|
||||
remoteParamNames = [p for p in remoteParamNames if not p in ['/run_id', '/rosdistro', '/rosversion']]
|
||||
remoteParamNames = [p for p in remoteParamNames if not p.startswith('/roslaunch/')]
|
||||
|
||||
assert not set(paramNames) ^ set(remoteParamNames), "parameter server keys do not match local: %s"%(set(paramNames)^set(remoteParamNames))
|
||||
|
||||
|
||||
# _testHasParam: test hasParam API
|
||||
def _testHasParam(self):
|
||||
master = self.master
|
||||
caller_id = '/node'
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/new_param')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/new_param', 1))
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, '/new_param')))
|
||||
# test with relative-name resolution
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, 'new_param')))
|
||||
|
||||
# test with param in sub-namespace
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/sub/sub2/new_param2')))
|
||||
# - verify that parameter tree does not exist yet (#587)
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/sub/sub2/')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/sub/sub2')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/sub/')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/sub')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/sub/sub2/new_param2', 1))
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, '/sub/sub2/new_param2')))
|
||||
# - verify that parameter tree now exists (#587)
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, '/sub/sub2/')))
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, '/sub/sub2')))
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, '/sub/')))
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, '/sub')))
|
||||
# test with relative-name resolution
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, 'sub/sub2/new_param2')))
|
||||
self.assert_(self.apiSuccess(master.hasParam('/sub/node', 'sub2/new_param2')))
|
||||
self.assert_(self.apiSuccess(master.hasParam('/sub/sub2/node', 'new_param2')))
|
||||
self.assert_(self.apiSuccess(master.hasParam('/sub/node', 'sub2')))
|
||||
self.assert_(self.apiSuccess(master.hasParam('/node', 'sub')))
|
||||
|
||||
# testSearchParam: test upwards-looking parameter search
|
||||
def _testSearchParam(self):
|
||||
master = self.master
|
||||
caller_id = '/node'
|
||||
# vals are mostly identical, save some randomness. we want
|
||||
# identical structure in order to stress lookup rules
|
||||
val1 = { 'level1_p1': random.randint(0, 10000),
|
||||
'level1_p2' : { 'level2_p2': random.randint(0, 10000) }}
|
||||
val2 = { 'level1_p1': random.randint(0, 10000),
|
||||
'level1_p2' : { 'level2_p2': random.randint(0, 10000) }}
|
||||
val3 = { 'level1_p1': random.randint(0, 10000),
|
||||
'level1_p2' : { 'level2_p2': random.randint(0, 10000) }}
|
||||
val4 = { 'level1_p1': random.randint(0, 10000),
|
||||
'level1_p2' : { 'level2_p2': random.randint(0, 10000) }}
|
||||
full_dict = {}
|
||||
|
||||
# set the val parameter at three levels so we can validate search
|
||||
caller_id = '/root'
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/param')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/param', val1))
|
||||
# - test param
|
||||
self.assertEquals('/param', self.apiSuccess(master.searchParam(caller_id, 'param')))
|
||||
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/level1/param')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/level1/param', val2))
|
||||
self.assertEquals(val2, self.apiSuccess(master.getParam(caller_id, '/level1/param')))
|
||||
# - test search param
|
||||
self.assertEquals('/param',
|
||||
self.apiSuccess(master.searchParam(caller_id, 'param')))
|
||||
self.assertEquals('/level1/param',
|
||||
self.apiSuccess(master.searchParam('/level1/node', 'param')))
|
||||
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/level1/level2/param')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/level1/level2/param', val3))
|
||||
# - test search param
|
||||
self.assertEquals('/param',
|
||||
self.apiSuccess(master.searchParam(caller_id, 'param')))
|
||||
self.assertEquals('/level1/param',
|
||||
self.apiSuccess(master.searchParam('/level1/node', 'param')))
|
||||
self.assertEquals('/level1/level2/param',
|
||||
self.apiSuccess(master.searchParam('/level1/level2/node', 'param')))
|
||||
self.assertEquals('/level1/level2/param',
|
||||
self.apiSuccess(master.searchParam('/level1/level2/level3/level4/node', 'param')))
|
||||
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/level1/level2/level3/level4/param')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/level1/level2/level3/level4/param', val4))
|
||||
# - test search param
|
||||
self.assertEquals('/param',
|
||||
self.apiSuccess(master.searchParam(caller_id, 'param')))
|
||||
self.assertEquals('/level1/param',
|
||||
self.apiSuccess(master.searchParam('/level1/node', 'param')))
|
||||
self.assertEquals('/level1/level2/param',
|
||||
self.apiSuccess(master.searchParam('/level1/level2/node', 'param')))
|
||||
self.assertEquals('/level1/level2/param',
|
||||
self.apiSuccess(master.searchParam('/level1/level2/level3/node', 'param')))
|
||||
self.assertEquals('/level1/level2/level3/level4/param',
|
||||
self.apiSuccess(master.searchParam('/level1/level2/level3/level4/node', 'param')))
|
||||
|
||||
# test completely different hierarchy, should go to top
|
||||
self.assertEquals('/param', self.apiSuccess(master.searchParam('/not/level1/level2/level3/level4/node', 'param')))
|
||||
# test looking for param/sub_param
|
||||
tests = [('/param', '/not/level1/level2/level3/level4/node'),
|
||||
('/level1/param', '/level1/node'),
|
||||
('/level1/param', '/level1/notlevel2/notlevel3/node'),
|
||||
('/level1/level2/param', '/level1/level2/node'),
|
||||
('/level1/level2/param', '/level1/level2/level3/node'),
|
||||
('/level1/level2/param', '/level1/level2/notlevel3/notlevel3/node'),
|
||||
('/level1/level2/level3/level4/param', '/level1/level2/level3/level4/node'),
|
||||
('/level1/level2/level3/level4/param', '/level1/level2/level3/level4/l5/l6/node'),
|
||||
]
|
||||
for pbase, caller_id in tests:
|
||||
self.assertEquals(pbase + '/level1_p1',
|
||||
self.apiSuccess(master.searchParam(caller_id, 'param/level1_p1')))
|
||||
key = pbase+'/level1_p2/level2_p2'
|
||||
self.assertEquals(key,
|
||||
self.apiSuccess(master.searchParam(caller_id, 'param/level1_p2/level2_p2')))
|
||||
# delete the sub key and repeat, should get the same result as searchParam does partial matches
|
||||
# - we may have already deleted the parameter in a previous iteration, so make sure
|
||||
if self.apiSuccess(master.hasParam(caller_id, key)):
|
||||
self.apiSuccess(master.deleteParam(caller_id, key))
|
||||
self.assertEquals(key,
|
||||
self.apiSuccess(master.searchParam(caller_id, 'param/level1_p2/level2_p2')))
|
||||
# to make sure that it didn't work spuriously, search for non-existent key
|
||||
self.assertEquals(pbase + '/non_existent',
|
||||
self.apiSuccess(master.searchParam(caller_id, 'param/non_existent')))
|
||||
self.assertEquals(pbase + '/level1_p2/non_existent',
|
||||
self.apiSuccess(master.searchParam(caller_id, 'param/level1_p2/non_existent')))
|
||||
|
||||
|
||||
## remove common keys that roslaunch places on param server
|
||||
def _filterDict(self, d):
|
||||
for k in ['run_id', 'roslaunch', 'rosversion', 'rosdistro']:
|
||||
if k in d:
|
||||
del d[k]
|
||||
return d
|
||||
|
||||
# testGetParam: test basic getParam behavior. Value encoding verified separately by testParamValues
|
||||
def _testGetParam(self):
|
||||
master = self.master
|
||||
caller_id = '/node'
|
||||
val = random.randint(0, 10000)
|
||||
|
||||
full_dict = {}
|
||||
|
||||
# very similar to has param sequence
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/new_param')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/new_param', val))
|
||||
full_dict['new_param'] = val
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam(caller_id, '/new_param')))
|
||||
# test with relative-name resolution
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam(caller_id, 'new_param')))
|
||||
# test full get
|
||||
ps_full_dict = self.apiSuccess(master.getParam(caller_id, '/'))
|
||||
self._filterDict(ps_full_dict)
|
||||
|
||||
self.assertEquals(full_dict, ps_full_dict)
|
||||
|
||||
# test with param in sub-namespace
|
||||
val = random.randint(0, 10000)
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/sub/sub2/new_param2')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/sub/sub2/new_param2', val))
|
||||
full_dict['sub'] = {'sub2': { 'new_param2': val }}
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam(caller_id, '/sub/sub2/new_param2')))
|
||||
# test with relative-name resolution
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam(caller_id, 'sub/sub2/new_param2')))
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam('/sub/node', 'sub2/new_param2')))
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam('/sub/sub2/node', 'new_param2')))
|
||||
# test that parameter server allows gets across namespaces (#493)
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam('/foo/bar/baz/blah/node', '/sub/sub2/new_param2')))
|
||||
# test full get
|
||||
ps_full_dict = self.apiSuccess(master.getParam(caller_id, '/'))
|
||||
self._filterDict(ps_full_dict)
|
||||
self.assertEquals(full_dict, ps_full_dict)
|
||||
|
||||
|
||||
# test that parameter server namespace-get (#587)
|
||||
val1 = random.randint(0, 10000)
|
||||
val2 = random.randint(0, 10000)
|
||||
val3 = random.randint(0, 10000)
|
||||
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/gains/P')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/gains/I')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/gains/D')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/gains')))
|
||||
|
||||
self.apiSuccess(master.setParam(caller_id, '/gains/P', val1))
|
||||
self.apiSuccess(master.setParam(caller_id, '/gains/I', val2))
|
||||
self.apiSuccess(master.setParam(caller_id, '/gains/D', val3))
|
||||
|
||||
pid = {'P': val1, 'I': val2, 'D': val3}
|
||||
full_dict['gains'] = pid
|
||||
self.assertEquals(pid,
|
||||
self.apiSuccess(master.getParam(caller_id, '/gains')))
|
||||
self.assertEquals(pid,
|
||||
self.apiSuccess(master.getParam(caller_id, '/gains/')))
|
||||
ps_full_dict = self.apiSuccess(master.getParam(caller_id, '/'))
|
||||
self._filterDict(ps_full_dict)
|
||||
self.assertEquals(full_dict, ps_full_dict)
|
||||
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/ns/gains/P')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/ns/gains/I')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/ns/gains/D')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/ns/gains')))
|
||||
|
||||
self.apiSuccess(master.setParam(caller_id, '/ns/gains/P', val1))
|
||||
self.apiSuccess(master.setParam(caller_id, '/ns/gains/I', val2))
|
||||
self.apiSuccess(master.setParam(caller_id, '/ns/gains/D', val3))
|
||||
full_dict['ns'] = {'gains': pid}
|
||||
|
||||
self.assertEquals(pid,
|
||||
self.apiSuccess(master.getParam(caller_id, '/ns/gains')))
|
||||
self.assertEquals({'gains': pid},
|
||||
self.apiSuccess(master.getParam(caller_id, '/ns/')))
|
||||
self.assertEquals({'gains': pid},
|
||||
self.apiSuccess(master.getParam(caller_id, '/ns')))
|
||||
ps_full_dict = self.apiSuccess(master.getParam(caller_id, '/'))
|
||||
self._filterDict(ps_full_dict)
|
||||
self.assertEquals(full_dict, ps_full_dict)
|
||||
|
||||
|
||||
# testSetParam: test basic setParam behavior. Value encoding verified separately by testParamValues
|
||||
def _testSetParam(self):
|
||||
master = self.master
|
||||
caller_id = '/node'
|
||||
val = random.randint(0, 10000)
|
||||
|
||||
# very similar to has param sequence
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/new_param')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/new_param', val))
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam(caller_id, '/new_param')))
|
||||
# test with relative-name resolution
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam(caller_id, 'new_param')))
|
||||
|
||||
# test type mutation, including from dictionary to value and back
|
||||
vals = ['a', {'a': 'b'}, 1, 1., 'foo', {'c': 'd'}, 4]
|
||||
for v in vals:
|
||||
self.apiSuccess(master.setParam(caller_id, '/multi/multi_param', v))
|
||||
self.assertEquals(v, self.apiSuccess(master.getParam(caller_id, 'multi/multi_param')))
|
||||
|
||||
# test with param in sub-namespace
|
||||
val = random.randint(0, 10000)
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/sub/sub2/new_param2')))
|
||||
self.apiSuccess(master.setParam(caller_id, '/sub/sub2/new_param2', val))
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam(caller_id, '/sub/sub2/new_param2')))
|
||||
# test with relative-name resolution
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam(caller_id, 'sub/sub2/new_param2')))
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam('/sub/node', 'sub2/new_param2')))
|
||||
self.assertEquals(val, self.apiSuccess(master.getParam('/sub/sub2/node', 'new_param2')))
|
||||
|
||||
# test that parameter server namespace-set (#587)
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/gains/P')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/gains/I')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/gains/D')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/gains')))
|
||||
|
||||
pid = {'P': random.randint(0, 10000), 'I': random.randint(0, 10000), 'D': random.randint(0, 10000)}
|
||||
self.apiSuccess(master.setParam(caller_id, '/gains', pid))
|
||||
self.assertEquals(pid, self.apiSuccess(master.getParam(caller_id, '/gains')))
|
||||
self.assertEquals(pid['P'], self.apiSuccess(master.getParam(caller_id, '/gains/P')))
|
||||
self.assertEquals(pid['I'], self.apiSuccess(master.getParam(caller_id, '/gains/I')))
|
||||
self.assertEquals(pid['D'], self.apiSuccess(master.getParam(caller_id, '/gains/D')))
|
||||
|
||||
subns = {'gains1': pid, 'gains2': pid}
|
||||
self.apiSuccess(master.setParam(caller_id, '/ns', subns))
|
||||
self.assertEquals(pid['P'], self.apiSuccess(master.getParam(caller_id, '/ns/gains1/P')))
|
||||
self.assertEquals(pid['I'], self.apiSuccess(master.getParam(caller_id, '/ns/gains1/I')))
|
||||
self.assertEquals(pid['D'], self.apiSuccess(master.getParam(caller_id, '/ns/gains1/D')))
|
||||
self.assertEquals(pid, self.apiSuccess(master.getParam(caller_id, '/ns/gains1')))
|
||||
self.assertEquals(pid, self.apiSuccess(master.getParam(caller_id, '/ns/gains2')))
|
||||
self.assertEquals(subns, self.apiSuccess(master.getParam(caller_id, '/ns/')))
|
||||
|
||||
# test empty dictionary set
|
||||
self.apiSuccess(master.setParam(caller_id, '/ns', {}))
|
||||
# - param should still exist
|
||||
self.assert_(self.apiSuccess(master.hasParam(caller_id, '/ns/')))
|
||||
# - value should remain dictionary
|
||||
self.assertEquals({}, self.apiSuccess(master.getParam(caller_id, '/ns/')))
|
||||
# - value2 below /ns/ should be erased
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/ns/gains1')))
|
||||
self.failIf(self.apiSuccess(master.hasParam(caller_id, '/ns/gains1/P')))
|
||||
|
||||
|
||||
# testParamValues: test storage of all XML-RPC compatible types"""
|
||||
def _testParamValues(self):
|
||||
try:
|
||||
from xmlrpc.client import Binary
|
||||
except ImportError:
|
||||
from xmlrpclib import Binary
|
||||
str_of_bytes = ''.join([chr(n) for n in range(0, 255)])
|
||||
if not isinstance(str_of_bytes, bytes):
|
||||
str_of_bytes = bytes(range(255))
|
||||
testVals = [
|
||||
['int', [0, 1024, 2147483647, -2147483647]],
|
||||
['boolean', [True, False]],
|
||||
#no longer testing null char
|
||||
#['string', ['', '\0', 'x', 'hello', ''.join([chr(n) for n in range(0, 255)])]],
|
||||
['unicode-string', [u'', u'hello', b'Andr\302\202'.decode('utf-8'), b'\377\376A\000n\000d\000r\000\202\000'.decode('utf-16')]],
|
||||
['string-easy-ascii', [chr(n) for n in range(32, 128)]],
|
||||
|
||||
#['string-mean-ascii-low', [chr(n) for n in range(9, 10)]], #separate for easier book-keeping
|
||||
#['string-mean-ascii-low', [chr(n) for n in range(1, 31)]], #separate for easier book-keeping
|
||||
#['string-mean-signed', [chr(n) for n in range(129, 256)]],
|
||||
['string', ['', 'x', 'hello-there', 'new\nline', 'tab\t']],
|
||||
['double', [0.0, math.pi, -math.pi, 3.4028235e+38, -3.4028235e+38]],
|
||||
#TODO: microseconds?
|
||||
['datetime', [datetime.datetime(2005, 12, 6, 12, 13, 14), datetime.datetime(1492, 12, 6, 12, 13, 14)]],
|
||||
['base64', [Binary(b''), Binary(b'\0'), Binary(str_of_bytes)]],
|
||||
['array', [[], [1, 2, 3], ['a', 'b', 'c'], [0.0, 0.1, 0.2, 2.0, 2.1, -4.0],
|
||||
[1, 'a', True], [[1, 2, 3], ['a', 'b', 'c'], [1.0, 2.1, 3.2]]]
|
||||
],
|
||||
]
|
||||
master = self.master
|
||||
|
||||
print("Putting parameters onto the server")
|
||||
# put our params into the parameter server
|
||||
contexts = ['', 'scope1', 'scope/sub1/sub2']
|
||||
myState = {}
|
||||
failures = []
|
||||
for ctx in contexts:
|
||||
self._setParam(ctx, myState, testVals, master)
|
||||
self._checkParamState(myState)
|
||||
|
||||
print("Deleting all of our parameters")
|
||||
# delete all of our parameters
|
||||
ctx = ''
|
||||
count = 0
|
||||
for key in list(myState.keys()):
|
||||
count += 1
|
||||
print("deleting [%s], [%s]" % (ctx, key))
|
||||
self.apiSuccess(master.deleteParam(ctx, key))
|
||||
del myState[key]
|
||||
# far too intensive to check every time
|
||||
if count % 50 == 0:
|
||||
self._checkParamState(myState)
|
||||
self._checkParamState(myState)
|
||||
|
||||
def _testEncapsulation(self):
|
||||
"""testEncapsulation: test encapsulation: setting same parameter at different levels"""
|
||||
master = self.master
|
||||
myState = {}
|
||||
self._checkParamState(myState)
|
||||
|
||||
testContexts = ['', 'en', 'en/sub1', 'en/sub2', 'en/sub1/sub2']
|
||||
for c in testContexts:
|
||||
c = make_global_ns(c)
|
||||
testKey = 'param1'
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
callerId = ns_join(c, "node")
|
||||
trueKey = ns_join(c, testKey)
|
||||
master.setParam(callerId, testKey, testVal)
|
||||
myState[trueKey] = testVal
|
||||
# make sure the master has the parameter under both keys and that they are equal
|
||||
v1 = self.apiSuccess(master.getParam('/', trueKey))
|
||||
v2 = self.apiSuccess(master.getParam(callerId, testKey))
|
||||
assert v1 == v2, "[%s]: %s vs. [%s,%s]: %s"%(trueKey, v1, callerId, testKey, v2)
|
||||
assert self.apiSuccess(master.hasParam(callerId, testKey)), testKey
|
||||
assert self.apiSuccess(master.hasParam('node', trueKey)), trueKey
|
||||
|
||||
self._checkParamState(myState)
|
||||
|
||||
def _testPrivateNames(self):
|
||||
master = self.master
|
||||
myState = {}
|
||||
self._checkParamState(myState)
|
||||
|
||||
testContexts = ['', 'sub1', 'sub1/sub2', 'sub1/sub2/sub3']
|
||||
for c in testContexts:
|
||||
c = make_global_ns(c)
|
||||
callerId = ns_join(c, "node")
|
||||
|
||||
keyStub = "param1"
|
||||
testKey = "~%s"%keyStub
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam(callerId, testKey, testVal)
|
||||
trueKey = ns_join(callerId, keyStub)
|
||||
myState[trueKey] = testVal
|
||||
|
||||
print("checking", trueKey)
|
||||
v1 = self.apiSuccess(master.getParam('/', trueKey))
|
||||
v2 = self.apiSuccess(master.getParam(callerId, testKey))
|
||||
assert v1 == v2, "[%s]: %s vs. [%s,%s]: %s"%(trueKey, v1, callerId, testKey, v2)
|
||||
assert self.apiSuccess(master.hasParam(callerId, testKey)), testKey
|
||||
assert self.apiSuccess(master.hasParam('node', trueKey)), trueKey
|
||||
|
||||
#test setting a local param on a different node
|
||||
testKey = ns_join("altnode","param2")
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam(callerId, testKey, testVal)
|
||||
trueKey = ns_join(c, testKey)
|
||||
altCallerId = ns_join(c, "altnode")
|
||||
myState[trueKey] = testVal
|
||||
|
||||
v1 = self.apiSuccess(master.getParam(altCallerId, "~param2"))
|
||||
v2 = self.apiSuccess(master.getParam(callerId, testKey))
|
||||
assert v1 == v2
|
||||
assert self.apiSuccess(master.hasParam(callerId, testKey)), testKey
|
||||
assert self.apiSuccess(master.hasParam(altCallerId, "~param2"))
|
||||
|
||||
self._checkParamState(myState)
|
||||
|
||||
## testScopeUp: test that parameter server can chain up scopes to find/delete parameters
|
||||
def _testScopeUp(self):
|
||||
master = self.master
|
||||
myState = {}
|
||||
self._checkParamState(myState)
|
||||
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('/', 'uparam1', testVal)
|
||||
myState['/uparam1'] = testVal
|
||||
assert testVal == self.apiSuccess(master.getParam('/node', 'uparam1'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest/node', 'uparam1'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest/sub1/node', 'uparam1'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest/sub1/sub2/node', 'uparam1'))
|
||||
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('/uptest2/sub1/node', 'uparam2', testVal)
|
||||
myState['/uptest2/sub1/uparam2'] = testVal
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest2/sub1/node', 'uparam2'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest2/sub1/sub2/node', 'uparam2'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest2/sub1/sub2/sub3/node', 'uparam2'))
|
||||
|
||||
# make sure we can ascend then descend
|
||||
if 0:
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('/uptest3/node', 'alt2/alt3/uparam3', testVal)
|
||||
myState['/uptest3/alt2/alt3/uparam3'] = testVal
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest3/sub1/node', 'alt2/alt3/uparam3'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest3/sub1/sub2/node', 'alt2/alt3/uparam3'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/uptest3/sub1/sub2/sub3/node', 'alt2/alt3/uparam3'))
|
||||
self._checkParamState(myState)
|
||||
|
||||
#verify upwards deletion
|
||||
self.apiSuccess(master.deleteParam('/uptest/sub1/sub2/node', 'uparam1'))
|
||||
del myState['/uparam1']
|
||||
self._checkParamState(myState)
|
||||
self.apiSuccess(master.deleteParam('/uptest2/sub1/sub2/sub3/node', 'uparam2'))
|
||||
del myState['/uptest2/sub1/uparam2']
|
||||
if 0:
|
||||
self.apiSuccess(master.deleteParam('/uptest3/sub1/sub2/sub3/node', 'alt2/alt3/uparam3'))
|
||||
del myState['/uptest3/alt2/alt3/uparam3']
|
||||
self._checkParamState(myState)
|
||||
|
||||
## testScopeDown: test scoping rules for sub contexts
|
||||
def _testScopeDown(self):
|
||||
master = self.master
|
||||
myState = {}
|
||||
self._checkParamState(myState)
|
||||
|
||||
# test that parameter server down not chain down scopes
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('/down/one/two/three/node', 'dparam1', testVal)
|
||||
myState['/down/one/two/three/dparam1'] = testVal
|
||||
assert not self.apiSuccess(master.hasParam('/down/one/node', 'dparam1'))
|
||||
assert not self.apiSuccess(master.hasParam('/down/one/two/node', 'dparam1'))
|
||||
self.apiError(master.getParam('/down/one/node', 'dparam1'))
|
||||
self.apiError(master.getParam('/down/one/two/node', 'dparam1'))
|
||||
|
||||
# test that parameter server allows setting of parameters further down (1)
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('/', '/down2/dparam2', testVal)
|
||||
myState['/down2/dparam2'] = testVal
|
||||
assert testVal == self.apiSuccess(master.getParam('/down2/node', 'dparam2'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/', 'down2/dparam2'))
|
||||
assert not self.apiSuccess(master.hasParam('/down2/node', 'down2/dparam2'))
|
||||
self.apiError(master.getParam('/down2/node', 'down2/dparam2'))
|
||||
self._checkParamState(myState)
|
||||
|
||||
# test that parameter server allows setting of parameters further down (2)
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('/', '/down3/sub/dparam3', testVal)
|
||||
myState['/down3/sub/dparam3'] = testVal
|
||||
assert testVal == self.apiSuccess(master.getParam('/down3/sub/node', 'dparam3'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/down3/node', 'sub/dparam3'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/', 'down3/sub/dparam3'))
|
||||
assert testVal == self.apiSuccess(master.getParam('/down3/sub/sub2/node', 'dparam3'))
|
||||
assert not self.apiSuccess(master.hasParam('/down3/sub/node', 'sub/dparam3'))
|
||||
assert not self.apiSuccess(master.hasParam('/down3/sub/node', 'down3/sub/dparam3'))
|
||||
self.apiError(master.getParam('/down3/sub/node', 'sub/dparam3'))
|
||||
self.apiError(master.getParam('/down3/sub/node', 'down3/sub/dparam3'))
|
||||
self._checkParamState(myState)
|
||||
|
||||
# test downwards deletion
|
||||
master.setParam('/', '/down4/sub/dparam4A', testVal)
|
||||
self.apiSuccess(master.deleteParam('/down4/sub/node', 'dparam4A'))
|
||||
assert not self.apiSuccess(master.hasParam('/down4/sub', 'dparam4A'))
|
||||
master.setParam('/', '/down4/sub/dparam4B', testVal)
|
||||
self.apiSuccess(master.deleteParam('/down4/node', 'sub/dparam4B'))
|
||||
assert not self.apiSuccess(master.hasParam('/down4/sub', 'dparam4B'))
|
||||
master.setParam('/', '/down4/sub/dparam4C', testVal)
|
||||
self.apiSuccess(master.deleteParam('/', 'down4/sub/dparam4C'))
|
||||
assert not self.apiSuccess(master.hasParam('/down4/sub/node', 'dparam4C'))
|
||||
self._checkParamState(myState)
|
||||
|
||||
4
thirdparty/ros/ros_comm/test/test_rosmaster/test/paramserver.test
vendored
Normal file
4
thirdparty/ros/ros_comm/test/test_rosmaster/test/paramserver.test
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<launch>
|
||||
<master type="test_rosmaster" />
|
||||
<include file="$(find test_rosmaster)/test/test-param-server.xml" />
|
||||
</launch>
|
||||
81
thirdparty/ros/ros_comm/test/test_rosmaster/test/rosclient.py
vendored
Normal file
81
thirdparty/ros/ros_comm/test/test_rosmaster/test/rosclient.py
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/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: test_embed_msg.py 1986 2008-08-26 23:57:56Z sfkwc $
|
||||
|
||||
import unittest
|
||||
try:
|
||||
from xmlrpc.client import ServerProxy
|
||||
except ImportError:
|
||||
from xmlrpclib import ServerProxy
|
||||
|
||||
import rosgraph
|
||||
|
||||
class TestRosClient(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.last_code = None
|
||||
self.last_msg = None
|
||||
self.last_val = None
|
||||
self.master = ServerProxy(rosgraph.get_master_uri())
|
||||
|
||||
def tearDown(self):
|
||||
self.master = None
|
||||
|
||||
## unit test assertion that fails if status code is not 1 and otherwise returns the value parameter
|
||||
## @param args [int, str, val]: returnv value from ROS API call
|
||||
## @return val value parameter from args (arg[2] for master/slave API)
|
||||
def apiSuccess(self, args):
|
||||
self.assert_(len(args) == 3, "invalid API return value triplet: %s"%str(args))
|
||||
self.last_code, self.last_msg, self.last_val = args
|
||||
assert self.last_code == 1, "status code is not 1: %s"%self.last_msg
|
||||
return self.last_val
|
||||
|
||||
## unit test assertions that fails if status code is not 0 and otherwise returns true
|
||||
## @param args [int, str, val]: returnv value from ROS API call
|
||||
## @return True if status code is 0
|
||||
def apiFail(self, args):
|
||||
self.assert_(len(args) == 3, "invalid API return value triplet: %s"%str(args))
|
||||
self.last_code, self.last_msg, self.last_val = args
|
||||
assert self.last_code == 0, "Call should have failed with status code 0: %s"%self.last_msg
|
||||
|
||||
## unit test assertion that fails if status code is not -1 and otherwise returns true
|
||||
## @return True if status code is -1
|
||||
def apiError(self, args, msg=None):
|
||||
self.assert_(len(args) == 3, "invalid API return value triplet: %s"%str(args))
|
||||
self.last_code, self.last_msg, self.last_val = args
|
||||
if msg:
|
||||
assert self.last_code == -1, "%s (return msg was %s)"%(msg, self.last_msg)
|
||||
else:
|
||||
assert self.last_code == -1, "Call should have returned error -1 code: %s"%self.last_msg
|
||||
|
||||
22
thirdparty/ros/ros_comm/test/test_rosmaster/test/rosmaster.test
vendored
Normal file
22
thirdparty/ros/ros_comm/test/test_rosmaster/test/rosmaster.test
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<launch>
|
||||
<master type="test_rosmaster" />
|
||||
<test test-name="test_rosmaster_simple_API" args="--simple" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_registerService_success" args="--regsrvsuccess" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_registerPublisher_success" args="--regpubsuccess" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_registerPublisher_types" args="--regpubtypes" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_registerSubscriber_simple_success" args="--regsubsimplesuccess" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
|
||||
<test test-name="test_rosmaster_unregisterService_success" args="--unregsrvsuccess" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_unregisterPublisher_success" args="--unregpubsuccess" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_unregisterSubscriber_success" args="--unregsubsuccess" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
|
||||
<test test-name="test_rosmaster_registerService_invalid" args="--regsrvinvalid" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_registerPublisher_invalid" args="--regpubinvalid" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_registerSubscriber_invalid" args="--regsubinvalid" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
|
||||
<test test-name="test_rosmaster_unregisterService_invalid" args="--unregsrvinvalid" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_unregisterPublisher_invalid" args="--unregpubinvalid" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
<test test-name="test_rosmaster_unregisterSubscriber_invalid" args="--unregsubinvalid" pkg="test_rosmaster" type="test_master_api.py" />
|
||||
|
||||
|
||||
</launch>
|
||||
16
thirdparty/ros/ros_comm/test/test_rosmaster/test/test-param-server.xml
vendored
Normal file
16
thirdparty/ros/ros_comm/test/test_rosmaster/test/test-param-server.xml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<!-- this test is designed to be included into another rostest XML file with a 'master' tag setting the appropriate 'type' -->
|
||||
<launch>
|
||||
<test test-name="param_server_encapsulation" pkg="test_rosmaster" type="test_ps_encapsulation.py" />
|
||||
<!-- values test usually takes just under a minute, so pad the time limit for slow builds -->
|
||||
<test time-limit="120.0" test-name="param_server_values" pkg="test_rosmaster" type="test_ps_values.py" />
|
||||
|
||||
<test test-name="param_server_search_param" pkg="test_rosmaster" type="test_ps_search_param.py" />
|
||||
|
||||
<test test-name="param_has_param" pkg="test_rosmaster" type="test_ps_has_param.py" />
|
||||
|
||||
<test test-name="param_get_param" pkg="test_rosmaster" type="test_ps_get_param.py" />
|
||||
<test test-name="param_set_param" pkg="test_rosmaster" type="test_ps_set_param.py" />
|
||||
|
||||
<!-- parameter server-side name resolution not supported -->
|
||||
<test test-name="param_server_private_names" pkg="test_rosmaster" type="test_ps_private_names.py" />
|
||||
</launch>
|
||||
883
thirdparty/ros/ros_comm/test/test_rosmaster/test/testMaster.py
vendored
Normal file
883
thirdparty/ros/ros_comm/test/test_rosmaster/test/testMaster.py
vendored
Normal file
@@ -0,0 +1,883 @@
|
||||
# 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$
|
||||
"""
|
||||
testMaster: ROS integration test cases for master XML-RPC API
|
||||
|
||||
To run, invoke nodes/testMaster
|
||||
"""
|
||||
|
||||
import os, sys, getopt, traceback, logging, socket
|
||||
import datetime, math, random
|
||||
try:
|
||||
from xmlrpc.client import DateTime, ServerProxy
|
||||
except ImportError:
|
||||
from xmlrpclib import DateTime, ServerProxy
|
||||
import unittest
|
||||
import rospy
|
||||
from rostest import *
|
||||
from testSlave import msMain
|
||||
|
||||
MYPKG = 'test_rosmaster'
|
||||
|
||||
HAS_PARAM = True
|
||||
|
||||
singletest = 'testGetFlowNames'
|
||||
singletest = None
|
||||
#singletest = 'testDotLocalNames'
|
||||
|
||||
def verifyNodeAddress(master, callerId, name, machine, addr, port):
|
||||
if not name:
|
||||
raise Exception("name is None")
|
||||
rmachine, raddr, rport = apiSuccess(master.getNodeAddress(callerId, name))
|
||||
if machine:
|
||||
assert rmachine == machine, "Node [%s] is running on '%s' instead of '%s'"%(name, rmachine, machine)
|
||||
if port:
|
||||
assert rport == port, "Node [%s] is running on '%s' instead of '%s'"%(name, rport, port)
|
||||
else:
|
||||
assert rport, "Node [%s] does not have a registered port"%name
|
||||
if addr:
|
||||
if addr == 'localhost':
|
||||
addr = socket.gethostname()
|
||||
if raddr == 'localhost':
|
||||
raddr = socket.gethostname()
|
||||
addrinfo = socket.getaddrinfo(addr, 0, 0, 0, socket.SOL_TCP)
|
||||
raddrinfo = socket.getaddrinfo(raddr, 0, 0, 0, socket.SOL_TCP)
|
||||
assert raddrinfo == addrinfo, "%s!=%s" % (raddrinfo, addrinfo)
|
||||
#ping the node
|
||||
apiSuccess(ServerProxy("http://%s:%s/"%(raddr, rport)).getPid(''))
|
||||
|
||||
def testGraphState(master, graphNodes, graphFlows):
|
||||
graph = apiSuccess(master.getGraph(''))
|
||||
diff = set(graph[0]) ^ set(graphNodes)
|
||||
assert not diff, "Graph nodes %s does not match expected %s: %s"%(graph[0], graphNodes, diff)
|
||||
# stringify for comparison
|
||||
expectedFlows = ["%s:%s:1"%f for f in graphFlows] # :1 = connected
|
||||
print graph[1]
|
||||
remoteFlows = ["%s:%s:%s"%(src,snk,c) for (src,snk,c) in graph[1]]
|
||||
if expectedFlows or remoteFlows:
|
||||
#assert set(expectedFlows) ^ set(remoteFlows), "Graph flows [%s] does not match expected [%s]"%(graph[1], graphFlows)
|
||||
diff = set(expectedFlows) ^ set(remoteFlows)
|
||||
assert not diff, "Graph flows %s does not match expected %s: %s"%(expectedFlows, remoteFlows, diff)
|
||||
|
||||
def testParamState(master, myState):
|
||||
callerId = 'master' #validate from root
|
||||
for (k, v) in myState.items():
|
||||
if HAS_PARAM:
|
||||
assert apiSuccess(master.hasParam(callerId, k))
|
||||
print "verifying parameter %s"%k
|
||||
v2 = apiSuccess(master.getParam(callerId, k))
|
||||
if isinstance(v2, DateTime):
|
||||
assert DateTime(v) == v2, "[%s]: %s != %s, %s"%(k, v, v2, v2.__class__)
|
||||
else:
|
||||
assert v == v2, "[%s]: %s != %s, %s"%(k, v, v2, v2.__class__)
|
||||
paramNames = myState.keys()
|
||||
remoteParamNames = apiSuccess(master.getParamNames(callerId))
|
||||
assert not set(paramNames) ^ set(remoteParamNames), "parameter server keys do not match local"
|
||||
|
||||
class ParamServerTestCase(ROSGraphTestCase):
|
||||
"""Parameter Server API Test Cases"""
|
||||
|
||||
def setUp(self):
|
||||
super(ParamServerTestCase, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super(ParamServerTestCase, self).tearDown()
|
||||
|
||||
def _testSetParam(self, ctx, myState, testVals, master):
|
||||
for type, vals in testVals:
|
||||
try:
|
||||
if ctx:
|
||||
callerId = "%s.node"%ctx
|
||||
else:
|
||||
callerId = "node"
|
||||
count = 0
|
||||
for val in vals:
|
||||
key = "%s-%s"%(type,count)
|
||||
print "master.setParam(%s,%s,%s)"%(callerId, key, val)
|
||||
master.setParam(callerId, key, val)
|
||||
if HAS_PARAM:
|
||||
assert apiSuccess(master.hasParam(callerId, key))
|
||||
if ctx:
|
||||
trueKey = "%s.%s"%(ctx, key)
|
||||
else:
|
||||
trueKey = key
|
||||
myState[trueKey] = val
|
||||
count += 1
|
||||
except:
|
||||
assert "getParam failed on type[%s], val[%s]"%(type,val)
|
||||
testParamState(master, myState)
|
||||
|
||||
def testParamValues(self):
|
||||
"""testParamValues: test storage of all XML-RPC compatible types"""
|
||||
try:
|
||||
from xmlrpc.client import Binary
|
||||
except ImportError:
|
||||
from xmlrpclib import Binary
|
||||
testVals = [
|
||||
['int', [0, 1024, 2147483647, -2147483647]],
|
||||
['boolean', [True, False]],
|
||||
['string', ['', '\0', 'x', 'hello', ''.join([chr(n) for n in range(0, 255)])]],
|
||||
['double', [0.0, math.pi, -math.pi, 3.4028235e+38, -3.4028235e+38]],
|
||||
#TODO: microseconds?
|
||||
['datetime', [datetime.datetime(2005, 12, 6, 12, 13, 14), datetime.datetime(1492, 12, 6, 12, 13, 14)]],
|
||||
['base64', [Binary(''), Binary('\0'), Binary(''.join([chr(n) for n in range(0, 255)]))]],
|
||||
['struct', [{ "a": 2, "b": 4},
|
||||
{"a" : "b", "c" : "d"},
|
||||
{"a" : {"b" : { "c" : "d"}}}]],
|
||||
['array', [[], [1, 2, 3], ['a', 'b', 'c'], [0.0, 0.1, 0.2, 2.0, 2.1, -4.0],
|
||||
[1, 'a', math.pi], [[1, 2, 3], ['a', 'b', 'c'], [1.0, 2.1, 3.2]]]
|
||||
],
|
||||
]
|
||||
master = self.master
|
||||
|
||||
print "Putting parameters onto the server"
|
||||
# put our params into the parameter server
|
||||
contexts = ['', 'scope1', 'scope2', 'scope.subscope1', 'scope.sub1.sub2']
|
||||
myState = {}
|
||||
for ctx in contexts:
|
||||
self._testSetParam(ctx, myState, testVals, master)
|
||||
|
||||
print "Deleting all of our parameters"
|
||||
# delete all of our parameters
|
||||
paramKeys = myState.keys()
|
||||
for key in paramKeys:
|
||||
apiSuccess(master.deleteParam('', key))
|
||||
del myState[key]
|
||||
testParamState(master, myState)
|
||||
|
||||
def testEncapsulation(self):
|
||||
"""testEncapsulation: test encapsulation: setting same parameter at different levels"""
|
||||
master = self.master
|
||||
myState = {}
|
||||
testParamState(master, myState)
|
||||
|
||||
testContexts = ['', 'en', 'en.sub1', 'en.sub2', 'en.sub1.sub2']
|
||||
for c in testContexts:
|
||||
testKey = 'param1'
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
if c:
|
||||
callerId = "%s.node"%c
|
||||
trueKey = "%s.%s"%(c,testKey)
|
||||
else:
|
||||
callerId ="node"
|
||||
trueKey = testKey
|
||||
master.setParam(callerId, testKey, testVal)
|
||||
myState[trueKey] = testVal
|
||||
# make sure the master has the parameter under both keys and that they are equal
|
||||
v1 = apiSuccess(master.getParam('', trueKey))
|
||||
v2 = apiSuccess(master.getParam(callerId, testKey))
|
||||
assert v1 == v2, "[%s]: %s vs. [%s,%s]: %s"%(trueKey, v1, callerId, testKey, v2)
|
||||
if HAS_PARAM:
|
||||
assert apiSuccess(master.hasParam(callerId, testKey)), testKey
|
||||
assert apiSuccess(master.hasParam('node', trueKey)), trueKey
|
||||
|
||||
testParamState(master, myState)
|
||||
|
||||
def testDotLocalNames(self):
|
||||
master = self.master
|
||||
myState = {}
|
||||
testParamState(master, myState)
|
||||
|
||||
testContexts = ['', 'sub1', 'sub1.sub2', 'sub1.sub2.sub3']
|
||||
for c in testContexts:
|
||||
if c:
|
||||
callerId = "%s.node"%c
|
||||
else:
|
||||
callerId = "node"
|
||||
testKey = ".param1"
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam(callerId, testKey, testVal)
|
||||
trueKey = callerId+testKey
|
||||
myState[trueKey] = testVal
|
||||
|
||||
v1 = apiSuccess(master.getParam('node', trueKey))
|
||||
v2 = apiSuccess(master.getParam(callerId, testKey))
|
||||
assert v1 == v2, "[%s]: %s vs. [%s,%s]: %s"%(trueKey, v1, callerId, testKey, v2)
|
||||
if HAS_PARAM:
|
||||
assert apiSuccess(master.hasParam(callerId, testKey)), testKey
|
||||
assert apiSuccess(master.hasParam('node', trueKey)), trueKey
|
||||
|
||||
#test setting a local param on a different node
|
||||
testKey = "altnode.param2"
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam(callerId, testKey, testVal)
|
||||
if c:
|
||||
trueKey = "%s.%s"%(c,testKey)
|
||||
altCallerId = "%s.altnode"%c
|
||||
else:
|
||||
trueKey = testKey
|
||||
altCallerId = "altnode"
|
||||
myState[trueKey] = testVal
|
||||
|
||||
v1 = apiSuccess(master.getParam(altCallerId, ".param2"))
|
||||
v2 = apiSuccess(master.getParam(callerId, testKey))
|
||||
assert v1 == v2
|
||||
if HAS_PARAM:
|
||||
assert apiSuccess(master.hasParam(callerId, testKey)), testKey
|
||||
assert apiSuccess(master.hasParam(altCallerId, ".param2"))
|
||||
|
||||
testParamState(master, myState)
|
||||
|
||||
def testScopeUp(self):
|
||||
"""testScopeUp: test that parameter server can chain up scopes to find/delete parameters"""
|
||||
master = self.master
|
||||
myState = {}
|
||||
testParamState(master, myState)
|
||||
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('', 'uparam1', testVal)
|
||||
myState['uparam1'] = testVal
|
||||
assert testVal == apiSuccess(master.getParam('node', 'uparam1'))
|
||||
assert testVal == apiSuccess(master.getParam('uptest.node', 'uparam1'))
|
||||
assert testVal == apiSuccess(master.getParam('uptest.sub1.node', 'uparam1'))
|
||||
assert testVal == apiSuccess(master.getParam('uptest.sub1.sub2.node', 'uparam1'))
|
||||
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('uptest2.sub1.node', 'uparam2', testVal)
|
||||
myState['uptest2.sub1.uparam2'] = testVal
|
||||
assert testVal == apiSuccess(master.getParam('uptest2.sub1.node', 'uparam2'))
|
||||
assert testVal == apiSuccess(master.getParam('uptest2.sub1.sub2.node', 'uparam2'))
|
||||
assert testVal == apiSuccess(master.getParam('uptest2.sub1.sub2.sub3.node', 'uparam2'))
|
||||
testParamState(master, myState)
|
||||
|
||||
#verify upwards deletion
|
||||
apiSuccess(master.deleteParam('uptest.sub1.sub2.node', 'uparam1'))
|
||||
del myState['uparam1']
|
||||
testParamState(master, myState)
|
||||
apiSuccess(master.deleteParam('uptest2.sub1.sub2.sub3.node', 'uparam2'))
|
||||
del myState['uptest2.sub1.uparam2']
|
||||
testParamState(master, myState)
|
||||
|
||||
def testScopeDown(self):
|
||||
"""testScopeDown: test scoping rules for sub contexts"""
|
||||
master = self.master
|
||||
myState = {}
|
||||
testParamState(master, myState)
|
||||
|
||||
# test that parameter server down not chain down scopes
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('down.one.two.three.node', 'dparam1', testVal)
|
||||
myState['down.one.two.three.dparam1'] = testVal
|
||||
if HAS_PARAM:
|
||||
assert not apiSuccess(master.hasParam('down.one', 'dparam1'))
|
||||
assert not apiSuccess(master.hasParam('down.one.two', 'dparam1'))
|
||||
apiError(master.getParam('down.one.node', 'dparam1'))
|
||||
apiError(master.getParam('down.one.two.node', 'dparam1'))
|
||||
|
||||
# test that parameter server allows setting of parameters further down (1)
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('node', 'down2.dparam2', testVal)
|
||||
myState['down2.dparam2'] = testVal
|
||||
assert testVal == apiSuccess(master.getParam('down2.node', 'dparam2'))
|
||||
assert testVal == apiSuccess(master.getParam('', 'down2.dparam2'))
|
||||
if HAS_PARAM:
|
||||
assert not apiSuccess(master.hasParam('down2.node', 'down2.dparam2'))
|
||||
apiError(master.getParam('down2.node', 'down2.dparam2'))
|
||||
testParamState(master, myState)
|
||||
|
||||
# test that parameter server allows setting of parameters further down (2)
|
||||
testVal = random.randint(-1000000, 100000)
|
||||
master.setParam('node', 'down3.sub.dparam3', testVal)
|
||||
myState['down3.sub.dparam3'] = testVal
|
||||
assert testVal == apiSuccess(master.getParam('down3.sub.node', 'dparam3'))
|
||||
assert testVal == apiSuccess(master.getParam('down3.node', 'sub.dparam3'))
|
||||
assert testVal == apiSuccess(master.getParam('', 'down3.sub.dparam3'))
|
||||
assert testVal == apiSuccess(master.getParam('down3.sub.sub2.node', 'dparam3'))
|
||||
if HAS_PARAM:
|
||||
assert not apiSuccess(master.hasParam('down3.sub.node', 'sub.dparam3'))
|
||||
assert not apiSuccess(master.hasParam('down3.sub.node', 'down3.sub.dparam3'))
|
||||
apiError(master.getParam('down3.sub.node', 'sub.dparam3'))
|
||||
apiError(master.getParam('down3.sub.node', 'down3.sub.dparam3'))
|
||||
testParamState(master, myState)
|
||||
|
||||
# test downwards deletion
|
||||
master.setParam('node', 'down4.sub.dparam4A', testVal)
|
||||
apiSuccess(master.deleteParam('down4.sub.node', 'dparam4A'))
|
||||
if HAS_PARAM:
|
||||
assert not apiSuccess(master.hasParam('down4.sub', 'dparam4A'))
|
||||
master.setParam('node', 'down4.sub.dparam4B', testVal)
|
||||
apiSuccess(master.deleteParam('down4.node', 'sub.dparam4B'))
|
||||
if HAS_PARAM:
|
||||
assert not apiSuccess(master.hasParam('down4.sub', 'dparam4B'))
|
||||
master.setParam('node', 'down4.sub.dparam4C', testVal)
|
||||
apiSuccess(master.deleteParam('', 'down4.sub.dparam4C'))
|
||||
if HAS_PARAM:
|
||||
assert not apiSuccess(master.hasParam('down4.sub.node', 'dparam4C'))
|
||||
testParamState(master, myState)
|
||||
|
||||
class MasterTestCase(ROSGraphTestCase):
|
||||
"""Master API Test Cases -- those not covered by ParamServer and AddKillNode"""
|
||||
|
||||
def setUp(self):
|
||||
super(MasterTestCase, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super(MasterTestCase, self).tearDown()
|
||||
|
||||
def _verifyFlowNameState(self, master, state):
|
||||
flows = apiSuccess(master.getFlowNames('node1', ''))
|
||||
assert len(flows) == len(state.values()), "Master reported a different number of flows"
|
||||
for val in state.values():
|
||||
assert val in flows, "flows does not contain %s : %s"%(val, flows)
|
||||
|
||||
def testPromoteFlow(self):
|
||||
master = self.master
|
||||
state = {}
|
||||
callerId = 'node1'
|
||||
type = 'common_flows/String'
|
||||
#setup node1 with outflows outflow1..3 and inflow1..3
|
||||
apiSuccess(master.registerNode(callerId, 'node1', 'localhost', 1234, []))
|
||||
for i in range(1, 4):
|
||||
for dir in ['inflow', 'outflow']:
|
||||
locator = 'node1:%s%s'%(dir, i)
|
||||
apiSuccess(master.registerFlow(callerId, 'node1', locator, dir, type))
|
||||
state[locator] = [locator, dir, type, 0]
|
||||
|
||||
#test promote of a non-existent flow
|
||||
apiError(master.promoteFlow(callerId, 'node1:notAFlow', 'node1:newNotAFlow'))
|
||||
# - :outflow1 should resolve to parent, which is a non-existent flow
|
||||
apiError(master.promoteFlow(callerId, ':outflow1', 'node1:newNotAFlow'))
|
||||
|
||||
## Play with Outflows
|
||||
#successfully promote outflow1 to global namespace
|
||||
dir = 'outflow'
|
||||
apiSuccess(master.promoteFlow(callerId, 'node1:outflow1', ':outflow1'))
|
||||
state[':outflow1'] = [':outflow1', dir, type, 1]
|
||||
# - verify with .local syntax
|
||||
apiSuccess(master.promoteFlow(callerId, '.:outflow2', ':outflow2'))
|
||||
state[':outflow2'] = [':outflow2', dir, type, 1]
|
||||
|
||||
## Play with Inflows
|
||||
#successfully promote inflow1 to the same namespace
|
||||
dir = 'inflow'
|
||||
tests = [
|
||||
['node1:inflow1', 'node1:newInflow1'],
|
||||
['node1:inflow2', 'sibling:inflow2'],
|
||||
['node1:inflow3', 'node1:subgraph1:inflow3']
|
||||
]
|
||||
for source, target in tests:
|
||||
apiSuccess(master.promoteFlow(callerId, source, target))
|
||||
state[target] = [target, dir, type, 1]
|
||||
|
||||
self._verifyFlowNameState(master, state)
|
||||
|
||||
#TODO: test promotion to an already promoted/registered flow name
|
||||
apiError(master.promoteFlow(callerId, 'node1:outflow1', 'node1:outflow2'))
|
||||
apiError(master.promoteFlow(callerId, 'node1:outflow2', ':outflow1'))
|
||||
apiError(master.promoteFlow(callerId, 'node1:inflow1', 'sibling:inflow2'))
|
||||
|
||||
#TODO: test promote of a promoted flow
|
||||
#TODO: test promote with both :flow and .:flow
|
||||
#TODO: test name resolution with subgraphs and callerIds better
|
||||
|
||||
def testRegisterFlow(self):
|
||||
master = self.master
|
||||
state = {}
|
||||
type = 'common_flows/String'
|
||||
for callerId in ['node1', 'subgraph.node1', 'grandparent.parent.node1']:
|
||||
#setup node1 with outflows outflow1..3 and inflow1..3
|
||||
apiSuccess(master.registerNode(callerId, 'node1', 'localhost', 1234, []))
|
||||
for i in range(1, 4):
|
||||
for dir in ['inflow', 'outflow']:
|
||||
if dir == 'inflow':
|
||||
locator = 'node1:%s%s'%(dir, i)
|
||||
else:
|
||||
locator = '.:%s%s'%(dir, i) #test .local resolution
|
||||
apiSuccess(master.registerFlow(callerId, 'node1', locator, dir, type))
|
||||
realLocator = '%s:%s%s'%(callerId, dir, i)
|
||||
state[realLocator] = [realLocator, dir, type, 0]
|
||||
#test register on a non-existent node
|
||||
apiError(master.registerFlow(callerId, 'notNode', 'notANode:outflow', 'outflow', type))
|
||||
#test register on bad locators
|
||||
apiError(master.registerFlow(callerId, 'node1', '', 'outflow', type))
|
||||
apiError(master.registerFlow(callerId, 'node1', 'badflow1', 'outflow', type))
|
||||
#test register on a bad direction
|
||||
apiError(master.registerFlow(callerId, 'node1', 'node1:badflow2', 'spiralflow', type))
|
||||
#test register on invalid types
|
||||
apiError(master.registerFlow(callerId, 'node1', 'node1:badflow3', 'outflow', ''))
|
||||
apiError(master.registerFlow(callerId, 'node1', 'node1:badflow4', 'outflow', 'faketype'))
|
||||
|
||||
#test register to an already promoted/registered flow name
|
||||
apiError(master.registerFlow(callerId, 'node1', 'node1:outflow1', 'outflow', type))
|
||||
apiSuccess(master.promoteFlow(callerId, 'node1:outflow1', 'node1:newOutflow1'))
|
||||
state['%s:newOutflow1'%callerId] = ['node1:newOutflow1', dir, type, 1]
|
||||
apiError(master.registerFlow(callerId, 'node1', 'node1:newOutflow1', 'outflow', type))
|
||||
|
||||
self._verifyFlowNameState(master, state)
|
||||
|
||||
def testUnregisterFlow(self):
|
||||
master = self.master
|
||||
state = {}
|
||||
type = 'common_flows/String'
|
||||
for callerId in ['node1', 'subgraph.node1', 'grandparent.parent.node1']:
|
||||
#setup node1 with outflows outflow1..3 and inflow1..3
|
||||
apiSuccess(master.registerNode(callerId, 'node1', 'localhost', 1234, []))
|
||||
for i in range(1, 4):
|
||||
for dir in ['inflow', 'outflow']:
|
||||
if dir == 'inflow':
|
||||
locator = rlocator = 'node1:%s%s'%(dir, i)
|
||||
else:
|
||||
locator = '.:%s%s'%(dir, i) #test .local resolution
|
||||
rlocator = 'node1:%s%s'%(dir, i) #test .local resolution
|
||||
apiSuccess(master.registerFlow(callerId, 'node1', locator, dir, type))
|
||||
realLocator = '%s:%s%s'%(callerId, dir, i)
|
||||
state[realLocator] = [realLocator, dir, type, 0]
|
||||
|
||||
self._verifyFlowNameState(master, state)
|
||||
|
||||
#test bad unregisters
|
||||
apiError(master.unregisterFlow(callerId, 'notANode:outflow'))
|
||||
apiError(master.unregisterFlow(callerId, ''))
|
||||
apiError(master.unregisterFlow(callerId.replace('node1', 'node2'), 'outflow1'))
|
||||
|
||||
apiSuccess(master.unregisterFlow(callerId, 'node1:outflow1'))
|
||||
del state['%s:outflow1'%callerId]
|
||||
apiSuccess(master.unregisterFlow(callerId, '.:outflow2'))
|
||||
del state['%s:outflow2'%callerId]
|
||||
apiSuccess(master.unregisterFlow(callerId.replace('node1', 'node2'), 'node1:outflow3'))
|
||||
del state['%s:outflow3'%callerId]
|
||||
apiSuccess(master.unregisterFlow('master', '%s:inflow1'%callerId))
|
||||
del state['%s:inflow1'%callerId]
|
||||
|
||||
self._verifyFlowNameState(master, state)
|
||||
|
||||
#test register to an already unregistered flow
|
||||
apiError(master.unregisterFlow(callerId, 'node1:outflow1'))
|
||||
|
||||
#test transitive unregisters
|
||||
apiSuccess(master.promoteFlow(callerId, 'node1:inflow3', ':inflow3A'))
|
||||
apiSuccess(master.promoteFlow(callerId, ':inflow3A', ':inflow3B'))
|
||||
# - should unregister both 3A and 3B
|
||||
apiSuccess(master.unregisterFlow(callerId, 'node1:inflow3'))
|
||||
del state['%s:inflow3'%callerId]
|
||||
|
||||
self._verifyFlowNameState(master, state)
|
||||
|
||||
def testGetFlowNames(self):
|
||||
master = self.master
|
||||
pkg,node = testNode
|
||||
subgraph = 'sub1.sub2'
|
||||
name = 'testGFN_A'
|
||||
port = apiSuccess(master.addNode('caller', subgraph, name, pkg, node, TEST_MACHINE, 0))
|
||||
#testNode must have :in and :out
|
||||
#:in and :out
|
||||
testFlowNames = ["%s:%s"%(name, v) for v in ["in", "out"]]
|
||||
print "FLOW NAMES", apiSuccess(master.getFlowNames('master', ''))
|
||||
flows = apiSuccess(master.getFlowNames('%s.caller'%subgraph, ''))
|
||||
assert not set([x[0] for x in flows]) ^ set(testFlowNames), "%s vs. %s"%([x[0] for x in flows], testFlowNames)
|
||||
|
||||
inDirs = [x[1] for x in flows if x[0].endswith(':in')]
|
||||
outDirs = [x[1] for x in flows if x[0].endswith(':out')]
|
||||
assert not filter(lambda x: x != "inflow", inDirs), inDirs
|
||||
assert not filter(lambda x: x != "outflow", outDirs), outDirs
|
||||
assert not filter(lambda x: x != "common_flows/String", [x[2] for x in flows]) #all flow types should be String
|
||||
assert not filter(lambda x: x, [x[3] for x in flows]) #promoted flag should all be zero
|
||||
|
||||
#test callerId scoping and subgraph parameter
|
||||
testFlowNames = ["%s.%s:%s"%(subgraph, name, v) for v in ["in", "out"]]
|
||||
flows = apiSuccess(master.getFlowNames('caller', subgraph))
|
||||
assert not set([x[0] for x in flows]) ^ set(testFlowNames), "%s vs. %s"%([x[0] for x in flows], testFlowNames)
|
||||
flows = apiSuccess(master.getFlowNames('caller', "%s.%s"%(subgraph, name)))
|
||||
assert not set([x[0] for x in flows]) ^ set(testFlowNames), "%s vs. %s"%([x[0] for x in flows], testFlowNames)
|
||||
|
||||
testFlowNames = ["sub2.%s:%s"%(name, v) for v in ["in", "out"]]
|
||||
flows = apiSuccess(master.getFlowNames('sub1.caller', 'sub2'))
|
||||
assert not set([x[0] for x in flows]) ^ set(testFlowNames), "%s vs. %s"%([x[0] for x in flows], testFlowNames)
|
||||
|
||||
|
||||
testFlowNames = ["%s.%s:%s"%(subgraph, name, v) for v in ["in", "out"]]
|
||||
flows = apiSuccess(master.getFlowNames('caller', ''))
|
||||
flowNames = [x[0] for x in flows]
|
||||
assert not set(flowNames) ^ set(testFlowNames)
|
||||
|
||||
|
||||
def testGetNodeAddress(self):
|
||||
def validate(val, callerId, name, port):
|
||||
assert len(val) == 3, "getNodeAddress did not return 3-element list for value field"
|
||||
assert type(val[0]) == str and type(val[1]) == str and type(val[2]) == int,\
|
||||
"getNodeAddress did not return (str, str, int) for value field"
|
||||
verifyNodeAddress(master, callerId, name, TEST_MACHINE, 'localhost', port)
|
||||
|
||||
#NOTE: this does not do full coverage on rospy, as many of the branch
|
||||
#conditions in rospy are inaccessible via external call (they required
|
||||
#corrupted data to be inserted into the master, which registerNode prevents)
|
||||
|
||||
master = self.master
|
||||
#test that invalid case still meets type spec
|
||||
code, msg, val = master.getNodeAddress('', 'testGetNodeAddress-fake')
|
||||
assert code == -1, "getNodeAddress did not return failure code 0 for non-existent node"
|
||||
assert len(val) == 3, "getNodeAddress did not return 3-element list for value field in error case"
|
||||
assert type(val[0]) == str and type(val[1]) == str and type(val[2]) == int,\
|
||||
"getNodeAddress did not return (str, str, int) for value field in error case"
|
||||
|
||||
#start a node to test valid case against
|
||||
name = 'testGetNodeAddress-1'
|
||||
port = 7981
|
||||
pkg, node = testNode
|
||||
apiSuccess(master.addNode('', '', name, pkg, node, TEST_MACHINE, port))
|
||||
val = apiSuccess(master.getNodeAddress('', name))
|
||||
validate(val, '', name, port)
|
||||
|
||||
#verify Graph Resource Name scoping rules
|
||||
name = 'testGetNodeAddress-2'
|
||||
port = 7982
|
||||
apiSuccess(master.addNode('', 'gna1.gna2', name, pkg, node, TEST_MACHINE, port))
|
||||
#make sure we have a node
|
||||
tests = [
|
||||
#test exact name matches
|
||||
['gna1.gna2.node', name],
|
||||
['gna1.node', 'gna2.%s'%name],
|
||||
['', 'gna1.gna2.%s'%name],
|
||||
#make sure that gNA searches upwards
|
||||
['gna1.gna2.gna3.node', name],
|
||||
]
|
||||
for test in tests:
|
||||
callerId, name = test
|
||||
validate(apiSuccess(master.getNodeAddress(callerId, name)), callerId, name, port)
|
||||
|
||||
#make sure that it gNA doesn't search upwards when subcontext is specified
|
||||
val = apiError(master.getNodeAddress('gna1.gna2', 'gna3.%s'%name))
|
||||
|
||||
def _verifyNodeDead(self, port):
|
||||
testUri = "http://localhost:%s/"%port
|
||||
try:
|
||||
ServerProxy(testUri).getPid('node')
|
||||
self.fail("test node is still running")
|
||||
except:
|
||||
pass
|
||||
|
||||
def testAddKillNode(self):
|
||||
"""testAddKillNode: test adding then killing nodes"""
|
||||
#TODO: more test cases
|
||||
master = self.master
|
||||
pkg,node = testNode
|
||||
apiError(master.killNode('node','nonexistentNode'))
|
||||
name = 'testAddKillA'
|
||||
port = apiSuccess(master.addNode('node', 'subgraph', name, pkg, node, TEST_MACHINE, 0))
|
||||
# - doesn't traverse across
|
||||
apiError(master.killNode('different.subgraph.node', name))
|
||||
# - doesn't traverse down
|
||||
apiError(master.killNode('node', name))
|
||||
# - doesn't traverse up
|
||||
apiError(master.killNode('subgraph.sub2.node', name))
|
||||
# - kill it
|
||||
apiSuccess(master.killNode('subgraph.node', name))
|
||||
|
||||
# - push on the name resolution a bit
|
||||
tests = [['node', '', 'testAddKillB'],
|
||||
['node', 'g1.g2', 'testAddKillB'],
|
||||
['node', 'g1', 'testAddKillB'],
|
||||
['g1.g2.node', 'g3', 'testAddKillB'],
|
||||
]
|
||||
for callerId, subcontext, nodeName in tests:
|
||||
port = apiSuccess(master.addNode(callerId, subcontext, nodeName, pkg, node, TEST_MACHINE, 0))
|
||||
if subcontext:
|
||||
name = "%s.%s"%(subcontext, nodeName)
|
||||
else:
|
||||
name = nodeName
|
||||
apiSuccess(master.killNode(callerId, name))
|
||||
self._verifyNodeDead(port)
|
||||
|
||||
def testAddNode(self):
|
||||
"""testAddNode: test master.addNode(callerId, subcontext, name, pkg, pkgNode, machine, port)"""
|
||||
master = self.master
|
||||
graphNodes = ['master']
|
||||
graphFlows = []
|
||||
# Failure cases
|
||||
pkg, node = testNode
|
||||
errors = [
|
||||
# - subcontext
|
||||
['', 12, 'testAddNodeError1', pkg, node, TEST_MACHINE, 0],
|
||||
#name
|
||||
['', '', 123, pkg, node, TEST_MACHINE, 0],
|
||||
# - invalid package implementation type
|
||||
['', '', 'testAddNodeError2', 123, node, TEST_MACHINE, 0],
|
||||
# - node impl name
|
||||
['', '', 'testAddNodeError3', pkg, '', TEST_MACHINE, 0],
|
||||
['', '', 'testAddNodeError4', pkg, 123, TEST_MACHINE, 0],
|
||||
# - machine parameter
|
||||
['', '', 'testAddNodeError6', pkg, node, 'unknown', 0],
|
||||
['', '', 'testAddNodeError7', pkg, 'noNode', 123, 0],
|
||||
# - port
|
||||
['', '', 'testAddNodeError8', pkg, node, TEST_MACHINE, -80],
|
||||
['', '', 'testAddNodeError9', pkg, node, TEST_MACHINE, "80"],
|
||||
]
|
||||
for args in errors:
|
||||
try:
|
||||
apiError(master.addNode(*args))
|
||||
except Exception, e:
|
||||
self.fail("addNodeError case failed with args[%s] and exception [%s]"%(args, e))
|
||||
# - non-existent node implementation (this takes awhile)
|
||||
apiFail(master.addNode('', '', 'testAddNodeFail1', pkg, 'notANode', TEST_MACHINE, 0))
|
||||
|
||||
testGraphState(master, graphNodes, graphFlows)
|
||||
tests = [[['','testAddNode1'], [TEST_MACHINE, 7980]],
|
||||
[['','testAddNode2'], [TEST_MACHINE, 0]],
|
||||
[['','testAddNode3'], ['', 0]],
|
||||
[['','testAddNode4'], [TEST_MACHINE, 0]],
|
||||
[['','testAddNode5'], [TEST_MACHINE, 0]],
|
||||
[['','testAddNode6'], [TEST_MACHINE, 0]],
|
||||
[['','testAddNode7'], [TEST_MACHINE, 0]],
|
||||
# subcontext
|
||||
[['push', 'testAddNode8'], [TEST_MACHINE, 0]],
|
||||
[['push.one.two', 'testAddNode9'], [TEST_MACHINE, 0]],
|
||||
[['stanford.addNodeTest','testAddNodeA'], [TEST_MACHINE, 0]],
|
||||
[['wg.addNodeTest', 'testAddNodeA'], [TEST_MACHINE, 0]],
|
||||
]
|
||||
for fullname, args in tests:
|
||||
print "testAddNode: testing", fullname
|
||||
subcontext, name = fullname
|
||||
if subcontext:
|
||||
fullname = '%s.%s'%(subcontext, name)
|
||||
else:
|
||||
fullname = name
|
||||
machine, port = args
|
||||
apiSuccess(master.addNode('', subcontext, name, pkg, node, machine, port))
|
||||
verifyNodeAddress(master, '', fullname, machine, 'localhost', port)
|
||||
graphNodes.append(fullname)
|
||||
testGraphState(master, graphNodes, graphFlows)
|
||||
# duplicate call should succeed
|
||||
apiSuccess(master.addNode('', subcontext, name, pkg, node, machine, port))
|
||||
|
||||
#TODO: more stress testing of name resolution with non-root callerIds
|
||||
|
||||
# duplicate call with different params should fail
|
||||
port = apiSuccess(master.addNode('node', 'duplicate.test', 'nodeA', pkg, node, TEST_MACHINE, 0))
|
||||
apiError(master.addNode('node', 'duplicate.test', 'nodeA', pkg, node, TEST_MACHINE, port + 1))
|
||||
apiError(master.addNode('node', 'duplicate.test', 'nodeA', pkg+'foo', node, TEST_MACHINE, port))
|
||||
apiError(master.addNode('node', 'duplicate.test', 'nodeA', pkg, node+'foo', TEST_MACHINE, port))
|
||||
#TODO: different machine
|
||||
|
||||
def testGetGraph(self):
|
||||
#TODO: in ROS 2.0, graph will be scoped by callerId. For now its safe to assume
|
||||
#that we are implicitly testing getGraph()
|
||||
pass
|
||||
|
||||
def testAddMachine(self):
|
||||
master = self.master
|
||||
host, port = masterAddr
|
||||
#test invalid calls on addMachine
|
||||
# - name
|
||||
apiError(master.addMachine('node', '', self.rosRoot, host, 22, '', ''))
|
||||
apiError(master.addMachine('node', 123, self.rosRoot, host, 22, '', ''))
|
||||
# - ros root
|
||||
apiError(master.addMachine('node', 'name', '', host, 22, '', ''))
|
||||
apiError(master.addMachine('node', 'name', 123, host, 22, '', ''))
|
||||
# - address
|
||||
apiError(master.addMachine('node', 'name', '', '', 22, '', ''))
|
||||
apiError(master.addMachine('node', 'name', '', 123, 22, '', ''))
|
||||
# - ssh port
|
||||
apiError(master.addMachine('node', 'name', '', host, -22, '', ''))
|
||||
apiError(master.addMachine('node', 'name', '', host, "22", '', ''))
|
||||
|
||||
tests = [
|
||||
['node', 'testAddMachine-1'],
|
||||
['g1.node', 'testAddMachine-2'],
|
||||
['g1.g2.g3.node', 'testAddMachine-3'],
|
||||
['g1.g2.node', 'testAddMachine-4'],
|
||||
]
|
||||
rosRoot = self.rosRoot
|
||||
for callerId, m in tests:
|
||||
apiSuccess(master.addMachine(callerId, m, rosRoot, host, 22, '', ''))
|
||||
# - duplicate safe
|
||||
apiSuccess(master.addMachine(callerId, m, rosRoot, host, 22, '', ''))
|
||||
# - test error for each parameter being changed
|
||||
apiError(master.addMachine(callerId, m, rosRoot+'/foo/', host, 22, '', ''))
|
||||
apiError(master.addMachine(callerId, m, rosRoot, 'www.google.com', 22, '', ''))
|
||||
apiError(master.addMachine(callerId, m, rosRoot, host, 21, '', ''))
|
||||
apiError(master.addMachine(callerId, m, rosRoot, host, 22, 'fake-user', ''))
|
||||
apiError(master.addMachine(callerId, m, rosRoot, host, 22, '', 'fake-password'))
|
||||
|
||||
#TODO: rewrite once master has a method for interrogating machines
|
||||
|
||||
def testRegisterNode_Flows(self):
|
||||
#TODO: test flows param
|
||||
pass
|
||||
|
||||
def testRegisterNode(self):
|
||||
master = self.master
|
||||
flows = []
|
||||
# - invalid name
|
||||
apiError(master.registerNode('', '', 'localhost', 80, flows))
|
||||
# - invalid address
|
||||
apiError(master.registerNode('', 'registerNodeFail2', '', 80, flows))
|
||||
# - invalid ports
|
||||
apiError(master.registerNode('', 'registerNodeFail3', 'localhost', -80, flows))
|
||||
apiError(master.registerNode('', 'registerNodeFail4', 'localhost', 0, flows))
|
||||
|
||||
#implicitly test registerNode via local exec of test node
|
||||
# - this actually tests the slave as much as the master, but I don't want
|
||||
# to call registerNode with correct parameters as it is ambiguous whether
|
||||
# or not the master should verify that the slave node actually exists
|
||||
testCases = [
|
||||
['', 'registerNodeExternal-1'],
|
||||
['', 'rne.registerNodeExternal-2'],
|
||||
['rne', 'registerNodeExternal-3'],
|
||||
['', 'rne.rne2.rne3.registerNodeExternal-4'],
|
||||
['rne', 'rne2.rne3.registerNodeExternal-5'],
|
||||
['rne.rne2.rne3', 'registerNodeExternal-6'],
|
||||
]
|
||||
for context, name in testCases:
|
||||
try:
|
||||
if context:
|
||||
fullName = "%s.%s"%(context, name)
|
||||
callerId = "%s.node"%context
|
||||
else:
|
||||
fullName = name
|
||||
callerId = "node"
|
||||
startTestNode(fullName)
|
||||
# Block until node is responsive before continuing
|
||||
# - give test node 4 seconds to start
|
||||
timeoutT = time.time() + 4.0
|
||||
node = getTestNode()
|
||||
val = None
|
||||
while time.time() < timeoutT and not val:
|
||||
try:
|
||||
_, _, val = node.getPid('')
|
||||
except:
|
||||
pass
|
||||
assert val, "unable to start test node for registerNode test case"
|
||||
# - we don't know the machine in this case
|
||||
verifyNodeAddress(master, callerId, name, None, testNodeAddr[0], testNodeAddr[1])
|
||||
finally:
|
||||
stopTestNode()
|
||||
|
||||
def testConnectFlow(self):
|
||||
master = self.master
|
||||
pkg, node = testNode
|
||||
graphNodes = ['master']
|
||||
graphFlows = []
|
||||
machine = TEST_MACHINE
|
||||
for i in range(1, 5):
|
||||
apiSuccess(master.addNode('m', '', 'baseTcfNode-%s'%i, pkg, node, machine, 0))
|
||||
graphNodes.append('baseTcfNode-%s'%i) #for testing up leveling
|
||||
apiSuccess(master.addNode('m', '', 'tcfNode-%s'%i, pkg, node, machine, 0))
|
||||
graphNodes.append('tcfNode-%s'%i)
|
||||
apiSuccess(master.addNode('m', 'tcf1', 'tcfNode-%s'%i, pkg, node, machine, 0))
|
||||
graphNodes.append('tcf1.tcfNode-%s'%i)
|
||||
apiSuccess(master.addNode('m', 'tcf2', 'tcfNode-%s'%i, pkg, node, machine, 0))
|
||||
graphNodes.append('tcf2.tcfNode-%s'%i)
|
||||
apiSuccess(master.addNode('m', 'tcf1.sub1', 'tcfNode-%s'%i, pkg, node, machine, 0))
|
||||
graphNodes.append('tcf1.sub1.tcfNode-%s'%i)
|
||||
apiSuccess(master.addNode('m', 'tcf2.sub1', 'tcfNode-%s'%i, pkg, node, machine, 0))
|
||||
graphNodes.append('tcf2.sub1.tcfNode-%s'%i)
|
||||
apiSuccess(master.addNode('m', 'tcf3', 'tcfNode3-%s'%i, pkg, node, machine, 0))
|
||||
graphNodes.append('tcf3.tcfNode3-%s'%i)
|
||||
testGraphState(master, graphNodes, graphFlows)
|
||||
|
||||
reliable = 1
|
||||
|
||||
# illegal cases
|
||||
illegal = [
|
||||
# - name resolution scope
|
||||
['node.tcf1', 'baseTcfNode-1:out', 'tcfNode-1:in'],
|
||||
['tcf1.node', 'tcfNode-1:out', 'baseTcfNode-1:in'],
|
||||
['tcf1.tcfNode-1', 'tcfNode-1:out', 'tcf1.tcfNode-1:in'],
|
||||
['tcf1.tcfNode-1', ':out', 'tcf1.tcfNode-1:in'],
|
||||
['tcf1.tcfNode-1', 'tcf1.tcfNode-2:out', ':in'],
|
||||
['tcf1.node', 'tcf1.tcfNode-1:out', 'tcfNode-1:in'],
|
||||
['tcf1.node', 'tcf2.tcfNode-1:out', 'tcfNode-1:in'],
|
||||
['tcf1.node', 'tcfNode-1:out', 'tcf2.tcfNode-1:in'],
|
||||
['tcf1.node', 'sub1.tcfNode-1:out', 'tcf2.sub1.tcfNode-1:in'],
|
||||
['tcf1.sub1.node','baseTcfNode-1:out', 'tcfNode-1:in'],
|
||||
['tcf1.sub1.node','sub1.tcfNode-1:out', 'tcfNode-1:in'],
|
||||
['tcf1.sub1.node','tcf2.tcfNode-1:out', 'tcfNode-1:in'],
|
||||
]
|
||||
for callerId, source, sink in illegal:
|
||||
apiError(master.connectFlow(callerId, source, sink, reliable))
|
||||
|
||||
# single source to sink sink
|
||||
singleCase = [
|
||||
#straight forward cases
|
||||
['node', 'tcfNode-1:out', 'tcfNode-2:in', 'tcfNode-1:out', 'tcfNode-2:in',],
|
||||
['tcfNode-1','tcf1.tcfNode-1:out', 'tcf1.tcfNode-2:in', 'tcf1.tcfNode-1:out', 'tcf1.tcfNode-2:in'],
|
||||
['tcf2.tcfNode-1', 'tcfNode-1:out', 'tcfNode-2:in', 'tcf2.tcfNode-1:out', 'tcf2.tcfNode-2:in'],
|
||||
['tcf1.tcfNode-2', 'sub1.tcfNode-1:out', 'sub1.tcfNode-2:in', 'tcf1.sub1.tcfNode-1:out', 'tcf1.sub1.tcfNode-2:in'],
|
||||
['tcf2.tcfNode-1', 'tcfNode-1:out', 'sub1.tcfNode-1:in', 'tcf2.tcfNode-1:out', 'tcf2.sub1.tcfNode-1:in'],
|
||||
|
||||
# '.locator' naming test
|
||||
['tcf2.sub1.tcfNode-1', '.:out', 'tcfNode-2:in', 'tcf2.sub1.tcfNode-1:out', 'tcf2.sub1.tcfNode-2:in'],
|
||||
['tcf3.tcfNode3-2', 'tcfNode3-1:out', '.:in', 'tcf3.tcfNode3-1:out', 'tcf3.tcfNode3-2:in'],
|
||||
]
|
||||
for callerId, source, sink, sourceFull, sinkFull in singleCase:
|
||||
apiSuccess(master.connectFlow(callerId, source, sink, reliable))
|
||||
graphFlows.append((sourceFull, sinkFull))
|
||||
testGraphState(master, graphNodes, graphFlows)
|
||||
|
||||
# - already connected
|
||||
# Spec is fuzzy here. It's possible that this should be a succeed.
|
||||
apiError(master.connectFlow('tcf2.node', 'tcfNode-1:out', 'tcfNode-2:in', reliable))
|
||||
apiError(master.connectFlow('node', 'tcf1.tcfNode-1:out', 'tcf1.tcfNode-2:in', reliable))
|
||||
|
||||
#TODO: test single source to multiple sinks
|
||||
#TODO: test multiple sources to single sink
|
||||
|
||||
|
||||
def testKillFlow(self):
|
||||
master = self.master
|
||||
if 0:
|
||||
master.killFlow(callerId, source, sink)
|
||||
|
||||
def testMisc(self):
|
||||
master = self.master
|
||||
assert master is not None, "master is None"
|
||||
masterUri = apiSuccess(master.getMasterUri(''))
|
||||
assert masterUri == apiSuccess(master.getMasterUri('a.different.id')), master.getMasterUri('a.different.id')
|
||||
assert (getMasterUri() == masterUri) or \
|
||||
(getMasterUriAlt() == masterUri), masterUri
|
||||
#getPid
|
||||
pid = apiSuccess(master.getPid(''))
|
||||
assert pid == apiSuccess(master.getPid('a.different.id')), master.getPid('a.different.id')
|
||||
#callerId must be string
|
||||
apiError(master.getPid(0))
|
||||
apiError(master.getMasterUri(0))
|
||||
#shutdown
|
||||
try:
|
||||
master.shutdown('some.id')
|
||||
except:
|
||||
pass
|
||||
time.sleep(0.1)
|
||||
try:
|
||||
code, status, val = master.getPid('')
|
||||
assert code < 1, "Master is still running after shutdown"
|
||||
except:
|
||||
pass
|
||||
|
||||
def testMasterMain(argv, stdout, env):
|
||||
return msMain(argv, stdout, env, [ParamServerTestCase, MasterTestCase], singletest)
|
||||
|
||||
if __name__ == '__main__':
|
||||
testMasterMain(sys.argv, sys.stdout, os.environ)
|
||||
|
||||
|
||||
343
thirdparty/ros/ros_comm/test/test_rosmaster/test/testSlave.py
vendored
Normal file
343
thirdparty/ros/ros_comm/test/test_rosmaster/test/testSlave.py
vendored
Normal file
@@ -0,0 +1,343 @@
|
||||
# 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 os
|
||||
import sys
|
||||
import string
|
||||
try:
|
||||
from xmlrpc.client import ServerProxy
|
||||
except ImportError:
|
||||
from xmlrpclib import ServerProxy
|
||||
|
||||
import rospy
|
||||
from rostest import *
|
||||
|
||||
singletest = None
|
||||
#singletest = 'testSourceKillFlow'
|
||||
|
||||
#TODO: test single source to multiple sinks
|
||||
#TODO: test multiple sources to single sink
|
||||
|
||||
# test_string_in
|
||||
# test_string_out
|
||||
|
||||
# test_primitives_in
|
||||
# test_primitives_out
|
||||
|
||||
# test_arrays_in
|
||||
# test_arrays_out
|
||||
|
||||
# test_header_in
|
||||
# test_header_out
|
||||
|
||||
_required_publications = 'test_string_out', 'test_primitives_out', 'test_arrays_out', 'test_header_out'
|
||||
_required_subscriptions = 'test_string_in', 'test_primitives_in', 'test_arrays_in', 'test_header_in'
|
||||
|
||||
## Expects a single test node to be running with name 'test_node' and subscribed to 'test_string'
|
||||
class SlaveTestCase(TestRosClient):
|
||||
|
||||
def setUp(self):
|
||||
super(SlaveTestCase, self).setUp()
|
||||
# retrieve handle on node
|
||||
self.caller_id = rospy.get_caller_id()
|
||||
self.node_api = self.apiSuccess(self.master.lookupNode(self.caller_id, 'test_node'))
|
||||
self.assert_(self.node_api.startswith('http'))
|
||||
self.node = ServerProxy(self.node_api)
|
||||
|
||||
def testGetPid(self):
|
||||
pid = self.apiSuccess(self.node.getPid(self.caller_id))
|
||||
self.assert_(pid > 0)
|
||||
|
||||
def testGetPublications(self):
|
||||
publications = self.apiSuccess(self.node.getPublications(self.caller_id))
|
||||
self.assert_(publications is not None)
|
||||
expected = [rospy.resolve_name(t) for t in _required_publications]
|
||||
missing = set(expected) - set(publications)
|
||||
self.failIf(len(missing), 'missing required topics: %s'%(','.join(missing)))
|
||||
|
||||
def _subTestSourceRequestFlow(self, testName, protocols, testEval):
|
||||
master = self.master
|
||||
tests = [
|
||||
[['testSourceRequestFlow-%s-nodeA','testSourceRequestFlow-%s-nodeB',],
|
||||
['node', 'testSourceRequestFlow-%s-nodeA.out', 'testSourceRequestFlow-%s-nodeB.in']],
|
||||
[['g1.testSourceRequestFlow-%s-nodeA','g1.testSourceRequestFlow-%s-nodeB',],
|
||||
['g1.node', 'testSourceRequestFlow-%s-nodeA.out', 'testSourceRequestFlow-%s-nodeB.in']],
|
||||
[['g1.g2.g3.testSourceRequestFlow-%s-nodeA','g1.g2.testSourceRequestFlow-%s-nodeB',],
|
||||
['g1.g2.node', 'g3.testSourceRequestFlow-%s-nodeA.out', 'testSourceRequestFlow-%s-nodeB.in']],
|
||||
[['g1.g2.testSourceRequestFlow-%s-nodeA','g1.g2.g3.testSourceRequestFlow-%s-nodeB',],
|
||||
['g1.g2.node', 'testSourceRequestFlow-%s-nodeA.out', 'g3.testSourceRequestFlow-%s-nodeB.in']],
|
||||
]
|
||||
sources = {}
|
||||
#start the nodes
|
||||
# - save the source as we will be making calls on it
|
||||
pkg, node = testNode
|
||||
for test in tests:
|
||||
sourceName, sinkName = [val%testName for val in test[0]]
|
||||
port = apiSuccess(master.addNode('', '', sourceName, pkg, node, TEST_MACHINE, 0))
|
||||
apiSuccess(master.addNode('', '', sinkName, pkg, node, TEST_MACHINE, 0))
|
||||
sourceUri = 'http://%s:%s/'%(testNodeAddr[0], port)
|
||||
sources[sourceName] = ServerProxy(sourceUri)
|
||||
|
||||
for test in tests:
|
||||
sourceName, sinkName = [val%testName for val in test[0]]
|
||||
source = sources[sourceName]
|
||||
callerId = test[1][0]
|
||||
sourceLocator, sinkLocator = [val%testName for val in test[1][1:]]
|
||||
args = source.sourceRequestFlow(callerId, sourceLocator, sinkLocator, protocols)
|
||||
testEval(args)
|
||||
#TODO: test locator name resolution
|
||||
|
||||
def testSourceRequestFlow_TCPROS1(self):
|
||||
def testEval(args):
|
||||
protocol = apiSuccess(args)
|
||||
assert type(protocol) == list
|
||||
assert string.upper(protocol[0]) == 'TCPROS', "source should have returned TCPROS as the desired protocol"
|
||||
assert len(protocol) == 3, "TCPROS parameter spec should be length 3"
|
||||
protocols = [['TCPROS']]
|
||||
self._subTestSourceRequestFlow('TCPROS1', protocols, testEval)
|
||||
|
||||
def testSourceRequestFlow_TCPROS2(self):
|
||||
def testEval(args):
|
||||
protocol = apiSuccess(args)
|
||||
assert type(protocol) == list
|
||||
assert string.upper(protocol[0]) == 'TCPROS', "source should have returned TCPROS as the desired protocol"
|
||||
assert len(protocol) == 3, "TCPROS parameter spec should be length 3"
|
||||
protocols = [['Fake1', 123, 132], ['Fake2', 1.0], ['Fake3'], ['Fake4', 'string'], ['Fake5', ['a', 'list'], ['a', 'nother', 'list']], ['TCPROS'], ['Fakelast', 'fake'] ]
|
||||
self._subTestSourceRequestFlow('TCPROS2', protocols, testEval)
|
||||
|
||||
def testSourceRequestFlow_Fail(self):
|
||||
protocols = [['Fake1', 123, 132], ['Fake2', 1.0], ['Fake3'], ['Fake4', 'string'], ['Fake5', ['a', 'list'], ['a', 'nother', 'list']], ['Fakelast', 'fake'] ]
|
||||
self._subTestSourceRequestFlow('Fail', protocols, apiFail)
|
||||
|
||||
def testSourceRequestFlow_Errors(self):
|
||||
slave = self.slave
|
||||
master = self.master
|
||||
#test that malformed locators return error codes
|
||||
apiError(slave.sourceRequestFlow('', '', ''))
|
||||
apiError(slave.sourceRequestFlow('', 'good.locator', 'badlocator'))
|
||||
apiError(slave.sourceRequestFlow('', 'badlocator', 'good.locator'))
|
||||
|
||||
# sourceKillFlow(callerId, sourceLocator, sinkLocator)
|
||||
#
|
||||
# * called by master
|
||||
# * returns int
|
||||
|
||||
def testSourceKillFlow(self):
|
||||
slave = self.slave
|
||||
master = self.master
|
||||
#test that malformed locators return error codes
|
||||
apiError(slave.sourceKillFlow('', '', ''))
|
||||
apiError(slave.sourceKillFlow('', 'good.locator', 'badlocator'))
|
||||
apiError(slave.sourceKillFlow('', 'badlocator', 'good.locator'))
|
||||
|
||||
tests = [
|
||||
[['testSourceKillFlow-nodeA','testSourceKillFlow-nodeB',],
|
||||
['node', 'testSourceKillFlow-nodeA.out', 'testSourceKillFlow-nodeB.in']],
|
||||
[['g1.testSourceKillFlow-nodeA','g1.testSourceKillFlow-nodeB',],
|
||||
['g1.node', 'testSourceKillFlow-nodeA.out', 'testSourceKillFlow-nodeB.in']],
|
||||
[['g1.g2.g3.testSourceKillFlow-nodeA','g1.g2.g3.testSourceKillFlow-nodeB',],
|
||||
['g1.g2.node', 'g3.testSourceKillFlow-nodeA.out', 'g3.testSourceKillFlow-nodeB.in']],
|
||||
[['g1.g2.testSourceKillFlow-nodeA','g1.g2.testSourceKillFlow-nodeB',],
|
||||
['g1.g2.node', 'testSourceKillFlow-nodeA.out', 'testSourceKillFlow-nodeB.in']],
|
||||
[['a1.g2.g3.testSourceKillFlow-nodeA','a1.g2.testSourceKillFlow-nodeB',],
|
||||
['a1.node', 'g2.g3.testSourceKillFlow-nodeA.out', 'g2.testSourceKillFlow-nodeB.in']],
|
||||
[['a1.g2.testSourceKillFlow-nodeA','a1.g2.g3.testSourceKillFlow-nodeB',],
|
||||
['a1.node', 'g2.testSourceKillFlow-nodeA.out', 'g2.g3.testSourceKillFlow-nodeB.in']],
|
||||
|
||||
]
|
||||
sources = {}
|
||||
#start the flows
|
||||
# - save the source as we will be making calls on it
|
||||
pkg, node = testNode
|
||||
for test in tests:
|
||||
sourceName, sinkName = test[0]
|
||||
# - start the source/sink nodes
|
||||
port = apiSuccess(master.addNode('', '', sourceName, pkg, node, TEST_MACHINE, 0))
|
||||
apiSuccess(master.addNode('', '', sinkName, pkg, node, TEST_MACHINE, 0))
|
||||
sourceUri = 'http://%s:%s/'%(testNodeAddr[0], port)
|
||||
sources[sourceName] = ServerProxy(sourceUri)
|
||||
# - start the flow
|
||||
callerId, sourceLocator, sinkLocator = test[1]
|
||||
apiSuccess(master.connectFlow(callerId, sourceLocator, sinkLocator, 1))
|
||||
|
||||
#attempt to kill flow with 1 wrong endpoint
|
||||
for test in tests:
|
||||
source = sources[test[0][0]]
|
||||
callerId, sourceLocator, sinkLocator = test[1]
|
||||
#sourceKill flow does a silent succeed if there is no flow to sink, but returns
|
||||
#0 flows killed
|
||||
val = apiSuccess(source.sourceKillFlow(callerId, sourceLocator, 'fake.sink'))
|
||||
assert val == 0, "flowsKilled should be 0 for non-existent flow [fakesink]"
|
||||
#sourceKill flow fails if source param does not refer to it
|
||||
apiError(source.sourceKillFlow(callerId, 'fake.source', sinkLocator))
|
||||
|
||||
#attempt to kill flow with wrong context
|
||||
for test in tests:
|
||||
source = sources[test[0][0]]
|
||||
callerId, sourceL, sinkL = test[1]
|
||||
for sub_test in tests:
|
||||
sub_callerId, sub_source, sub_sink = test[1]
|
||||
if sub_callerId == callerId and sub_source == sourceL and sub_sink == sinkL:
|
||||
continue
|
||||
val = apiSuccess(source.sourceKillFlow(sub_callerId, sub_source, sub_sink))
|
||||
assert val == 0, "flowsKilled should be 0 for non-existent flow [different context: %s,%s,%s on %s,%s,%s]"%(sub_callerId, sub_source, sub_sink, callerId, sourceL, sinkL)
|
||||
|
||||
# try to kill all flows on the source that we started
|
||||
for test in tests:
|
||||
source = sources[test[0][0]]
|
||||
callerId, sourceLocator, sinkLocator = test[1]
|
||||
val = apiSuccess(source.sourceKillFlow(callerId, sourceLocator, sinkLocator))
|
||||
assert type(val) == int
|
||||
assert val == 1, "Source did not report 1 flow killed: %s, %s"%(val, getLastMsg())
|
||||
#TODO: test locator name resolution
|
||||
|
||||
sinkTests = [
|
||||
[['testSinkConnectFlow-nodeA','testSinkConnectFlow-nodeB',],
|
||||
['node', 'testSinkConnectFlow-nodeA.out', 'testSinkConnectFlow-nodeB.in']],
|
||||
[['g1.testSinkConnectFlow-nodeA','g1.testSinkConnectFlow-nodeB',],
|
||||
['g1.node', 'testSinkConnectFlow-nodeA.out', 'testSinkConnectFlow-nodeB.in']],
|
||||
[['g1.g2.g3.testSinkConnectFlow-nodeA','g1.g2.testSinkConnectFlow-nodeB',],
|
||||
['g1.g2.node', 'g3.testSinkConnectFlow-nodeA.out', 'testSinkConnectFlow-nodeB.in']],
|
||||
[['g1.g2.testSinkConnectFlow-nodeA','g1.g2.g3.testSinkConnectFlow-nodeB',],
|
||||
['g1.g2.node', 'testSinkConnectFlow-nodeA.out', 'g3.testSinkConnectFlow-nodeB.in']],
|
||||
#separate subgraphs
|
||||
[['a1.a2.testSinkConnectFlow-nodeA','b1.b2.testSinkConnectFlow-nodeB',],
|
||||
['node', 'a1.a2.testSinkConnectFlow-nodeA.out', 'b1.b2.testSinkConnectFlow-nodeB.in']],
|
||||
# '.locator' resolution
|
||||
[['c1.node.testSinkConnectFlow-nodeA','c1.node2.testSinkConnectFlow-nodeB',],
|
||||
['c1.node2', 'node.testSinkConnectFlow-nodeA.out', '.testSinkConnectFlow-nodeB.in']],
|
||||
|
||||
]
|
||||
|
||||
def _sink_StartNodes(self, tests):
|
||||
"""
|
||||
Test subroutine to startup all the nodes specified in the tests
|
||||
"""
|
||||
master = self.master
|
||||
sourceUris = {}
|
||||
sinks = {}
|
||||
#start the nodes
|
||||
# - save the sink as we will be making calls on it
|
||||
pkg, node = testNode
|
||||
for test in tests:
|
||||
sourceName, sinkName = test[0]
|
||||
sourcePort = apiSuccess(master.addNode('', '', sourceName, pkg, node, TEST_MACHINE, 0))
|
||||
sinkPort = apiSuccess(master.addNode('', '', sinkName, pkg, node, TEST_MACHINE, 0))
|
||||
sourceUri = 'http://%s:%s/'%(testNodeAddr[0], sourcePort)
|
||||
sinkUri = 'http://%s:%s/'%(testNodeAddr[0], sinkPort)
|
||||
sourceUris[sourceName] = sourceUri
|
||||
sinks[sinkName] = ServerProxy(sinkUri)
|
||||
return sourceUris, sinks
|
||||
|
||||
def _sink_StartFlows(self, tests, sourceUris, sinks):
|
||||
"""
|
||||
subroutine to connect the flows specified in the tests, purely
|
||||
using the sink API.
|
||||
|
||||
In the future it would be nice to verify that the flow truly
|
||||
exists, but for now trust what the sink says
|
||||
"""
|
||||
reliable = 1 #don't have UDP yet
|
||||
for test in tests:
|
||||
sourceName, sinkName = test[0]
|
||||
sourceUri = sourceUris[sourceName]
|
||||
sink = sinks[sinkName]
|
||||
callerId, sourceLocator, sinkLocator = test[1]
|
||||
print "Testing", test
|
||||
val = apiSuccess(sink.sinkConnectFlow(callerId, sourceLocator, sinkLocator, sourceUri, reliable))
|
||||
assert type(val) == int
|
||||
|
||||
def _sink_KillFlows(self, tests, sinks):
|
||||
"""
|
||||
subroutine to kill the flows specified in the tests, purely
|
||||
using the sink API (i.e. source will still be running)
|
||||
|
||||
In the future it would be nice to verify that the flow was
|
||||
killed, but for now trust what the sink says"""
|
||||
reliable = 1 #don't have UDP yet
|
||||
for test in tests:
|
||||
sourceName, sinkName = test[0]
|
||||
sink = sinks[sinkName]
|
||||
callerId, sourceLocator, sinkLocator = test[1]
|
||||
print "Testing", test
|
||||
assert 1 == apiSuccess(sink.sinkKillFlow(callerId, sourceLocator, sinkLocator)),\
|
||||
"sink did not report 1 flow killed: %s, %s"%(getLastVal(), getLastMsg())
|
||||
|
||||
#sinkConnectFlow(sourceLocator, sinkLocator, sourceXmlRpcURI, reliable)
|
||||
# * API call on the sink of a flow. Called by master.
|
||||
# * master requests that sink negotiate with the source to establish the flow
|
||||
# * returns meaningless int
|
||||
# * synchronous call, blocks until success/fail
|
||||
|
||||
def testSinkConnectFlow(self):
|
||||
master = self.master
|
||||
sourceUris, sinks = self._sink_StartNodes(self.sinkTests)
|
||||
self._sink_StartFlows(self.sinkTests, sourceUris, sinks)
|
||||
|
||||
# sinkKillFlow(sourceLocator, sinkLocator)
|
||||
# * called by master
|
||||
def testSinkKillFlow(self):
|
||||
slave = self.slave
|
||||
master = self.master
|
||||
apiError(slave.sinkKillFlow('', '', ''))
|
||||
|
||||
#startup the standard sink tests
|
||||
sourceUris, sinks = self._sink_StartNodes(self.sinkTests)
|
||||
self._sink_StartFlows(self.sinkTests, sourceUris, sinks)
|
||||
self._sink_KillFlows(self.sinkTests, sinks)
|
||||
|
||||
def testMisc(self):
|
||||
slave = self.slave
|
||||
assert slave is not None, "slave is None"
|
||||
#getMasterUri
|
||||
masterUri = apiSuccess(slave.getMasterUri(''))
|
||||
assert getMasterUri() == masterUri or getMasterUriAlt() == masterUri, masterUri
|
||||
assert masterUri == apiSuccess(slave.getMasterUri('a.different.id'))
|
||||
#getPid
|
||||
pid = apiSuccess(slave.getPid(''))
|
||||
assert pid == apiSuccess(slave.getPid('a.different.id'))
|
||||
#callerId must be string
|
||||
apiError(slave.getPid(0))
|
||||
apiError(slave.getMasterUri(0))
|
||||
try:
|
||||
slave.shutdown('some.id')
|
||||
except:
|
||||
pass
|
||||
time.sleep(0.1)
|
||||
try:
|
||||
code, status, val = slave.getPid('')
|
||||
assert code < 1, "Slave is still running after shutdown"
|
||||
except:
|
||||
pass
|
||||
|
||||
204
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_master_api.py
vendored
Executable file
204
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_master_api.py
vendored
Executable file
@@ -0,0 +1,204 @@
|
||||
#!/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.
|
||||
|
||||
## Integration test for empty services to test serializers
|
||||
## and transport
|
||||
|
||||
PKG='test_rosmaster'
|
||||
NAME = 'test_master'
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import rospy
|
||||
|
||||
from master import MasterApiTestCase, set_node_name
|
||||
|
||||
# Due to the need to have a fresh master for each of these test cases,
|
||||
# we have to go through the pain of exposing each of the test cases one-by-one
|
||||
|
||||
class MasterSimpleApi(MasterApiTestCase):
|
||||
def testGetPid(self):
|
||||
self._testGetPid()
|
||||
def testGetUri(self):
|
||||
self._testGetUri()
|
||||
|
||||
class MasterRegisterServiceSuccess(MasterApiTestCase):
|
||||
def testRegisterServiceSuccess(self):
|
||||
self._testRegisterServiceSuccess()
|
||||
|
||||
class MasterRegisterPublisherSuccess(MasterApiTestCase):
|
||||
def testRegisterPublisherSuccess(self):
|
||||
self._testRegisterPublisherSuccess()
|
||||
class MasterRegisterPublisherTypes(MasterApiTestCase):
|
||||
## #591: this test may change if we make registering '*' unsupported
|
||||
def testRegisterPublisherTypes(self):
|
||||
self._testRegisterPublisherTypes()
|
||||
|
||||
class MasterRegisterSubscriberSimpleSuccess(MasterApiTestCase):
|
||||
def testRegisterSubscriberSimpleSuccess(self):
|
||||
self._testRegisterSubscriberSimpleSuccess()
|
||||
|
||||
|
||||
class MasterUnregisterServiceSuccess(MasterApiTestCase):
|
||||
def testUnregisterServiceSuccess(self):
|
||||
self._testUnregisterServiceSuccess()
|
||||
|
||||
class MasterUnregisterPublisherSuccess(MasterApiTestCase):
|
||||
def testUnregisterPublisherSuccess(self):
|
||||
self._testUnregisterPublisherSuccess()
|
||||
|
||||
class MasterUnregisterSubscriberSuccess(MasterApiTestCase):
|
||||
def testUnregisterSubscriberSuccess(self):
|
||||
self._testUnregisterSubscriberSuccess()
|
||||
|
||||
class MasterRegisterServiceInvalid(MasterApiTestCase):
|
||||
def testRegisterServiceInvalid(self):
|
||||
self._testRegisterServiceInvalid()
|
||||
|
||||
class MasterRegisterPublisherInvalid(MasterApiTestCase):
|
||||
def testRegisterPublisherInvalid(self):
|
||||
self._testRegisterPublisherInvalid()
|
||||
|
||||
class MasterRegisterSubscriberInvalid(MasterApiTestCase):
|
||||
def testRegisterSubscriberInvalid(self):
|
||||
self._testRegisterSubscriberInvalid()
|
||||
|
||||
|
||||
class MasterUnregisterServiceInvalid(MasterApiTestCase):
|
||||
def testUnregisterServiceInvalid(self):
|
||||
self._testUnregisterServiceInvalid()
|
||||
|
||||
class MasterUnregisterPublisherInvalid(MasterApiTestCase):
|
||||
def testUnregisterPublisherInvalid(self):
|
||||
self._testUnregisterPublisherInvalid()
|
||||
|
||||
class MasterUnregisterSubscriberInvalid(MasterApiTestCase):
|
||||
def testUnregisterSubscriberInvalid(self):
|
||||
self._testUnregisterSubscriberInvalid()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# this is terribly complicated on the account that we want a fresh master for each test, so we cannot
|
||||
# run all the tests as a single test node. instead, we have to have a separate test node per test.
|
||||
|
||||
import optparse
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser(usage="usage: %prog [options] topic", prog=NAME)
|
||||
|
||||
# have to redeclare --text/--cov options, which are standard rostest options
|
||||
parser.add_option("--text",dest="text_ignore", default=False,
|
||||
action="store_true", help="rostest standard option")
|
||||
parser.add_option("--cov",dest="cov_ignore", default=False,
|
||||
action="store_true", help="rostest standard option")
|
||||
|
||||
parser.add_option("--simple",dest="simple", default=False,
|
||||
action="store_true", help="MasterSimpleApi")
|
||||
|
||||
parser.add_option("--gtest_output",dest="gtest_output", default='',
|
||||
help="xml output file")
|
||||
|
||||
parser.add_option("--regsrvsuccess", dest="regsrvsuccess", default=False,
|
||||
action="store_true", help="MasterRegisterServiceSuccess")
|
||||
parser.add_option("--regpubsuccess", dest="regpubsuccess", default=False,
|
||||
action="store_true", help="MasterRegisterPublisherSuccess")
|
||||
parser.add_option("--regpubtypes", dest="regpubtypes", default=False,
|
||||
action="store_true", help="MasterRegisterPublisherTypes")
|
||||
parser.add_option("--regsubsimplesuccess", dest="regsubsimplesuccess", default=False,
|
||||
action="store_true", help="MasterRegisterSubscriberSimpleSuccess")
|
||||
|
||||
|
||||
parser.add_option("--unregsrvsuccess", dest="unregsrvsuccess", default=False,
|
||||
action="store_true", help="MasterUnregisterServiceSuccess")
|
||||
parser.add_option("--unregpubsuccess", dest="unregpubsuccess", default=False,
|
||||
action="store_true", help="MasterUnregisterPublisherSuccess")
|
||||
parser.add_option("--unregsubsuccess", dest="unregsubsuccess", default=False,
|
||||
action="store_true", help="MasterUnregisterSubscriberSuccess")
|
||||
|
||||
parser.add_option("--regsrvinvalid", dest="regsrvinvalid", default=False,
|
||||
action="store_true", help="MasterRegisterServiceInvalid")
|
||||
parser.add_option("--regsubinvalid", dest="regsubinvalid", default=False,
|
||||
action="store_true", help="MasterRegisterSubscriberInvalid")
|
||||
parser.add_option("--regpubinvalid", dest="regpubinvalid", default=False,
|
||||
action="store_true", help="MasterRegisterPublisherInvalid")
|
||||
|
||||
parser.add_option("--unregsrvinvalid", dest="unregsrvinvalid", default=False,
|
||||
action="store_true", help="MasterUnregisterServiceInvalid")
|
||||
parser.add_option("--unregsubinvalid", dest="unregsubinvalid", default=False,
|
||||
action="store_true", help="MasterUnregisterSubscriberInvalid")
|
||||
parser.add_option("--unregpubinvalid", dest="unregpubinvalid", default=False,
|
||||
action="store_true", help="MasterUnregisterPublisherInvalid")
|
||||
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if options.simple:
|
||||
cls = MasterSimpleApi
|
||||
|
||||
elif options.regsrvsuccess:
|
||||
cls = MasterRegisterServiceSuccess
|
||||
elif options.regpubsuccess:
|
||||
cls = MasterRegisterPublisherSuccess
|
||||
elif options.regpubtypes:
|
||||
cls = MasterRegisterPublisherTypes
|
||||
elif options.regsubsimplesuccess:
|
||||
cls = MasterRegisterSubscriberSimpleSuccess
|
||||
|
||||
elif options.unregsrvsuccess:
|
||||
cls = MasterUnregisterServiceSuccess
|
||||
elif options.unregpubsuccess:
|
||||
cls = MasterUnregisterPublisherSuccess
|
||||
elif options.unregsubsuccess:
|
||||
cls = MasterUnregisterSubscriberSuccess
|
||||
|
||||
elif options.regsrvinvalid:
|
||||
cls = MasterRegisterServiceInvalid
|
||||
elif options.regpubinvalid:
|
||||
cls = MasterRegisterPublisherInvalid
|
||||
elif options.regsubinvalid:
|
||||
cls = MasterRegisterSubscriberInvalid
|
||||
|
||||
elif options.unregsrvinvalid:
|
||||
cls = MasterUnregisterServiceInvalid
|
||||
elif options.unregpubinvalid:
|
||||
cls = MasterUnregisterPublisherInvalid
|
||||
elif options.unregsubinvalid:
|
||||
cls = MasterUnregisterSubscriberInvalid
|
||||
|
||||
if not cls:
|
||||
parser.error("you must specify a test to run with an [options] flag")
|
||||
|
||||
set_node_name(NAME)
|
||||
rospy.init_node(NAME, disable_rostime=True)
|
||||
import rostest
|
||||
rostest.rosrun(PKG, NAME, cls, sys.argv)
|
||||
47
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_node_api.py
vendored
Executable file
47
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_node_api.py
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/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.
|
||||
|
||||
PKG='test_rosmaster'
|
||||
NAME = 'test_node_api'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from node import NodeApiTestCase, set_node_name
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
set_node_name(NAME)
|
||||
rostest.rosrun(PKG, NAME, NodeApiTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_encapsulation.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_encapsulation.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG = 'test_rosmaster'
|
||||
NAME = 'test_ps_encapsulation'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server_test_case import ParamServerTestCase
|
||||
|
||||
class PsEncapsulationTestCase(ParamServerTestCase):
|
||||
def testEncapsulation(self):
|
||||
return self._testEncapsulation()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsEncapsulationTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_get_param.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_get_param.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG='test_rosmaster'
|
||||
NAME = 'test_ps_has_param'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server_test_case import ParamServerTestCase
|
||||
|
||||
class PsGetParamTestCase(ParamServerTestCase):
|
||||
def testGetParam(self):
|
||||
return self._testGetParam()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsGetParamTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_has_param.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_has_param.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG = 'test_rosmaster'
|
||||
NAME = 'test_ps_has_param'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server_test_case import ParamServerTestCase
|
||||
|
||||
class PsHasParamTestCase(ParamServerTestCase):
|
||||
def testHasParam(self):
|
||||
return self._testHasParam()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsHasParamTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_private_names.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_private_names.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG = 'test_rosmaster'
|
||||
NAME = 'test_ps_private_names'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server_test_case import ParamServerTestCase
|
||||
|
||||
class PsPrivateNamesTestCase(ParamServerTestCase):
|
||||
def testPrivateNames(self):
|
||||
return self._testPrivateNames()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsPrivateNamesTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_scope_down.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_scope_down.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG = 'test_rosmaster'
|
||||
NAME = 'test_ps_scope_down'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server import ParamServerTestCase
|
||||
|
||||
class PsScopeDownTestCase(ParamServerTestCase):
|
||||
def testScopeDown(self):
|
||||
return self._testScopeDown()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsScopeDownTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_scope_up.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_scope_up.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG = 'test_rosmaster'
|
||||
NAME = 'test_ps_scope_up'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server import ParamServerTestCase
|
||||
|
||||
class PsScopeUpTestCase(ParamServerTestCase):
|
||||
def testScopeUp(self):
|
||||
return self._testScopeUp()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsScopeUpTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_search_param.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_search_param.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG = 'test_rosmaster'
|
||||
NAME = 'test_ps_values'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server_test_case import ParamServerTestCase
|
||||
|
||||
class PsSearchParamTestCase(ParamServerTestCase):
|
||||
def testSearchParam(self):
|
||||
return self._testSearchParam()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsSearchParamTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_set_param.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_set_param.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG = 'test_rosmaster'
|
||||
NAME = 'test_ps_has_param'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server_test_case import ParamServerTestCase
|
||||
|
||||
class PsSetParamTestCase(ParamServerTestCase):
|
||||
def testSetParam(self):
|
||||
return self._testSetParam()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsSetParamTestCase, sys.argv)
|
||||
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_values.py
vendored
Executable file
50
thirdparty/ros/ros_comm/test/test_rosmaster/test/test_ps_values.py
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/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.
|
||||
|
||||
PKG = 'test_rosmaster'
|
||||
NAME = 'test_ps_values'
|
||||
|
||||
import sys
|
||||
|
||||
import rospy
|
||||
import rostest
|
||||
|
||||
from param_server_test_case import ParamServerTestCase
|
||||
|
||||
class PsValuesTestCase(ParamServerTestCase):
|
||||
def testParamValues(self):
|
||||
return self._testParamValues()
|
||||
|
||||
if __name__ == '__main__':
|
||||
rospy.init_node(NAME)
|
||||
rostest.rosrun(PKG, NAME, PsValuesTestCase, sys.argv)
|
||||
Reference in New Issue
Block a user