00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import os
00036 import sys
00037 import string
00038 import time
00039 import xmlrpclib
00040
00041 import rospy
00042 import rosgraph
00043
00044 from rosclient import *
00045
00046 NODE_INTEGRATION_NAME = "node_integration_test"
00047
00048 _name = None
00049
00050
00051 def set_node_name(name):
00052 global _name
00053 _name = name
00054
00055
00056
00057
00058 def get_caller_id():
00059 if _name is None:
00060 raise Exception("set_node_name has not been called yet")
00061 ros_ns = os.environ.get(rosgraph.ROS_NAMESPACE, rosgraph.names.GLOBALNS)
00062 return rosgraph.names.ns_join(ros_ns, _name)
00063
00064 class _MasterTestCase(TestRosClient):
00065
00066 def __init__(self, *args):
00067 super(_MasterTestCase, self).__init__(*args)
00068 self.ns = os.environ.get(rosgraph.ROS_NAMESPACE, rosgraph.names.GLOBALNS)
00069 self.caller_id = get_caller_id()
00070
00071 def setUp(self):
00072 super(_MasterTestCase, self).setUp()
00073 self.master_uri = os.environ.get(rosgraph.ROS_MASTER_URI, None)
00074 self._checkUri(self.master_uri)
00075 self.master = xmlrpclib.ServerProxy(self.master_uri)
00076
00077
00078 def _checkUri(self, uri):
00079 import urlparse
00080 parsed = urlparse.urlparse(uri)
00081 self.assert_(parsed[0] in ['http', 'https'], 'protocol [%s] in [%s] invalid'%(parsed[0], uri))
00082 self.assert_(parsed[1], 'host missing [%s]'%uri)
00083 if not sys.version.startswith('2.4'):
00084 self.assert_(parsed.port, 'port missing/invalid [%s]'%uri)
00085
00086
00087 class MasterApiTestCase(_MasterTestCase):
00088
00089
00090 def _testGetMasterUri(self):
00091
00092 self.apiError(self.master.getMasterUri())
00093
00094 uri = self.apiSuccess(self.master.getMasterUri(self.caller_id))
00095 self._checkUri(uri)
00096
00097
00098 import urlparse
00099 parsed = urlparse.urlparse(uri)
00100 parsed2 = urlparse.urlparse(self.master_uri)
00101
00102 self.assertEquals(parsed.port, parsed2.port, "expected ports do not match")
00103
00104
00105 def _testGetPid(self):
00106
00107 self.apiError(self.master.getPid())
00108
00109 pid = self.apiSuccess(self.master.getPid(self.caller_id))
00110 self.assert_(pid > 0)
00111
00112
00113 def _testGetUri(self):
00114
00115 self.apiError(self.master.getUri())
00116
00117 uri = self.apiSuccess(self.master.getUri(self.caller_id))
00118 self.assert_(type(uri) == str)
00119
00120
00121 def _subTestRegisterServiceSuccess(self):
00122 master = self.master
00123
00124 caller_id = '/service_node'
00125 caller_api = 'http://localhost:4567/'
00126 service_base = '/service'
00127
00128
00129 for i in xrange(0, 10):
00130 service_name = "%s-%s"%(service_base, i)
00131 service_api = 'rosrpc://localhost:123%s/'%i
00132
00133 self.apiSuccess(master.registerService(caller_id, service_name, service_api, caller_api))
00134
00135 val = self.apiSuccess(master.lookupService(caller_id, service_name))
00136 self.assertEquals(service_api, val)
00137 val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
00138 self.assertEquals(caller_api, val)
00139
00140 _, _, srvs = self.apiSuccess(master.getSystemState(self.caller_id))
00141 for j in xrange(0, i+1):
00142 jservice_name = "%s-%s"%(service_base, j)
00143 jentry = [jservice_name, [caller_id]]
00144 self.assert_(jentry in srvs, "master service list %s is missing %s"%(srvs, jentry))
00145
00146
00147
00148
00149
00150 def _testRegisterServiceSuccess(self):
00151 self._subTestRegisterServiceSuccess()
00152
00153 def _testUnregisterServiceSuccess(self):
00154 self._subTestRegisterServiceSuccess()
00155 master = self.master
00156 caller_id = '/service_node'
00157 caller_api = 'http://localhost:4567/'
00158 service_base = '/service'
00159
00160 for i in xrange(0, 10):
00161 service_name = "%s-%s"%(service_base, i)
00162 service_api = 'rosrpc://localhost:123%s/'%i
00163
00164
00165 code, msg, val = master.unregisterService(caller_id, service_name, service_api)
00166 self.assertEquals(code, 1, "code != 1, return message was [%s]"%msg)
00167
00168
00169 self.apiError(master.lookupService(self.caller_id, service_name), "master has a reference to unregistered service. message from master for unregister was [%s]"%msg)
00170
00171 if i < 9:
00172 val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
00173 self.assertEquals(caller_api, val, "master prematurely invalidated node entry for [%s] (lookupNode)"%caller_id)
00174
00175 _, _, srvs = self.apiSuccess(master.getSystemState(self.caller_id))
00176 for j in xrange(0, i+1):
00177 jservice_name = "%s-%s"%(service_base, j)
00178 jentry = [jservice_name, [caller_id]]
00179 self.assert_(jentry not in srvs, "master service list %s should not have %s"%(srvs, jentry))
00180 for j in xrange(i+1, 10):
00181 jservice_name = "%s-%s"%(service_base, j)
00182 jentry = [jservice_name, [caller_id]]
00183 self.assert_(jentry in srvs, "master service list %s is missing %s"%(srvs, jentry))
00184
00185
00186
00187
00188
00189
00190 self.apiError(master.lookupNode(self.caller_id, caller_id), "master has a stale reference to unregistered service node API")
00191 _, _, srvs = self.apiSuccess(master.getSystemState(self.caller_id))
00192 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')]
00193 self.assertEquals(0, len(srvs), "all services should have been unregistered: %s"%srvs)
00194
00195 def _testRegisterServiceInvalid(self):
00196 master = self.master
00197
00198 service = '/service'
00199 service_api = 'rosrpc://localhost:1234/'
00200 caller_api = 'http://localhost:4567/'
00201
00202
00203 self.apiError(master.registerService())
00204 self.apiError(master.registerService(self.caller_id, service))
00205 self.apiError(master.registerService(self.caller_id, service, service_api))
00206
00207
00208 self.apiError(master.registerService(self.caller_id, '', service_api, caller_api))
00209 self.apiError(master.registerService(self.caller_id, service, '', caller_api))
00210 self.apiError(master.registerService(self.caller_id, service, service_api, ''))
00211
00212 def _testUnregisterServiceInvalid(self):
00213 master = self.master
00214
00215 service = '/service'
00216 service_api = 'rosrpc://localhost:1234/'
00217
00218
00219 self.apiError(master.unregisterService())
00220 self.apiError(master.unregisterService(self.caller_id, service))
00221
00222
00223 self.apiError(master.unregisterService(self.caller_id, '', service_api))
00224 self.apiError(master.unregisterService(self.caller_id, service, ''))
00225
00226 def _testRegisterPublisherInvalid(self):
00227 master = self.master
00228
00229 topic = '/pub_topic'
00230 topic_type = 'test_rosmaster/String'
00231 caller_api = 'http://localhost:4567/'
00232
00233
00234 self.apiError(master.registerPublisher())
00235 self.apiError(master.registerPublisher(self.caller_id, topic))
00236 self.apiError(master.registerPublisher(self.caller_id, topic, topic_type))
00237
00238
00239 self.apiError(master.registerPublisher(self.caller_id, '', topic_type, caller_api))
00240 self.apiError(master.registerPublisher(self.caller_id, topic, '', caller_api))
00241 self.apiError(master.registerPublisher(self.caller_id, topic, topic_type, ''))
00242
00243 def _testUnregisterPublisherInvalid(self):
00244 master = self.master
00245
00246 topic = '/pub_topic'
00247 caller_api = 'http://localhost:4567/'
00248
00249
00250 self.apiError(master.unregisterPublisher())
00251 self.apiError(master.unregisterPublisher(self.caller_id, topic))
00252
00253
00254 self.apiError(master.unregisterPublisher(self.caller_id, '', caller_api))
00255 self.apiError(master.unregisterPublisher(self.caller_id, topic, ''))
00256
00257 def _testRegisterSubscriberInvalid(self):
00258 master = self.master
00259
00260 topic = '/sub_topic'
00261 topic_type = 'test_rosmaster/String'
00262 caller_api = 'http://localhost:4567/'
00263
00264
00265 self.apiError(master.registerSubscriber())
00266 self.apiError(master.registerSubscriber(self.caller_id, topic))
00267 self.apiError(master.registerSubscriber(self.caller_id, topic, topic_type))
00268
00269
00270 self.apiError(master.registerSubscriber(self.caller_id, '', topic_type, caller_api))
00271 self.apiError(master.registerSubscriber(self.caller_id, topic, '', caller_api))
00272 self.apiError(master.registerSubscriber(self.caller_id, topic, topic_type, ''))
00273
00274 def _testUnregisterSubscriberInvalid(self):
00275 master = self.master
00276
00277 topic = '/sub_topic'
00278 caller_api = 'http://localhost:4567/'
00279
00280
00281 self.apiError(master.registerSubscriber())
00282 self.apiError(master.registerSubscriber(self.caller_id, topic))
00283
00284
00285 self.apiError(master.unregisterSubscriber(self.caller_id, '', caller_api))
00286 self.apiError(master.unregisterSubscriber(self.caller_id, topic, ''))
00287
00288
00289 def _subTestRegisterPublisherSuccess(self):
00290 master = self.master
00291
00292 caller_id = '/pub_node'
00293 caller_api = 'http://localhost:4567/'
00294 topic_base = '/pub_topic'
00295 topic_type = 'test_rosmaster/String'
00296
00297
00298 for i in xrange(0, 10):
00299 topic_name = "%s-%s"%(topic_base, i)
00300
00301 self.apiSuccess(master.registerPublisher(caller_id, topic_name, topic_type, caller_api))
00302
00303
00304 val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
00305 self.assertEquals(caller_api, val)
00306
00307 val = self.apiSuccess(master.getPublishedTopics(self.caller_id, '/'))
00308 self.assert_([topic_name, topic_type] in val, "master does not know topic type: %s"%val)
00309
00310 val = self.apiSuccess(master.getTopicTypes(self.caller_id))
00311 self.assert_([topic_name, topic_type] in val, "master does not know topic type: %s"%val)
00312
00313 pubs, _, _ = self.apiSuccess(master.getSystemState(self.caller_id))
00314 for j in xrange(0, i+1):
00315 jtopic_name = "%s-%s"%(topic_base, j)
00316 jentry = [jtopic_name, [caller_id]]
00317 self.assert_(jentry in pubs, "master pub/sub list %s is missing %s"%(pubs, jentry))
00318
00319
00320
00321
00322 def _testRegisterPublisherTypes(self):
00323 master = self.master
00324 caller_id = '/pub_node'
00325 caller_api = 'http://localhost:4567/'
00326 topic_name = '/type_test_pub_topic'
00327
00328
00329 val = self.apiSuccess(master.registerPublisher(caller_id, topic_name, '*', caller_api))
00330 self.assertEquals([], val)
00331 val = self.apiSuccess(master.getPublishedTopics(self.caller_id, '/'))
00332 self.assert_([topic_name, '*'] in val, "master is not reporting * as type: %s"%val)
00333
00334 val = self.apiSuccess(master.getTopicTypes(self.caller_id))
00335 self.assert_([topic_name, '*'] in val, "master is not reporting * as type: %s"%val)
00336
00337
00338 for t in ['test_rosmaster/String', '*']:
00339 val = self.apiSuccess(master.registerPublisher(caller_id, topic_name, t, caller_api))
00340 self.assertEquals([], val)
00341 val = self.apiSuccess(master.getPublishedTopics(self.caller_id, '/'))
00342 self.assert_([topic_name, 'test_rosmaster/String'] in val, "master is not reporting test_rosmaster/String as type: %s"%val)
00343
00344 val = self.apiSuccess(master.getTopicTypes(self.caller_id))
00345 self.assert_([topic_name, 'test_rosmaster/String'] in val, "master is not reporting test_rosmaster/String as type: %s"%val)
00346
00347
00348 def _testRegisterPublisherSuccess(self):
00349 self._subTestRegisterPublisherSuccess()
00350
00351
00352 master = self.master
00353 topic = '/pub_topic-0'
00354 type = 'test_rosmaster/String'
00355 pub_caller_api = 'http://localhost:4567/'
00356
00357 subs = []
00358 for i in xrange(5678, 5685):
00359 api = 'http://localhost:%s'%i
00360 subs.append(api)
00361 self.apiSuccess(master.registerSubscriber('/sub_node-%i'%i, topic, type, api))
00362 val = self.apiSuccess(master.registerPublisher('/pub_node', topic, type, pub_caller_api))
00363 self.assertEquals(subs, val)
00364
00365 def _testUnregisterPublisherSuccess(self):
00366 self._subTestRegisterPublisherSuccess()
00367 master = self.master
00368 caller_id = '/pub_node'
00369 caller_api = 'http://localhost:4567/'
00370 topic_base = '/pub_topic'
00371
00372 for i in xrange(0, 10):
00373 topic_name = "%s-%s"%(topic_base, i)
00374
00375
00376 code, msg, val = master.unregisterPublisher(caller_id, topic_name, caller_api)
00377 self.assertEquals(code, 1, "code != 1, return message was [%s]"%msg)
00378
00379
00380 if i < 9:
00381 val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
00382 self.assertEquals(caller_api, val, "master prematurely invalidated node entry for [%s] (lookupNode)"%caller_id)
00383
00384 pubs, _, _ = self.apiSuccess(master.getSystemState(self.caller_id))
00385 for j in xrange(0, i+1):
00386 jtopic_name = "%s-%s"%(topic_base, j)
00387 jentry = [jtopic_name, [caller_id]]
00388 self.assert_(jentry not in pubs, "master pub/sub list %s should not have %s"%(pubs, jentry))
00389 for j in xrange(i+1, 10):
00390 jtopic_name = "%s-%s"%(topic_base, j)
00391 jentry = [jtopic_name, [caller_id]]
00392 self.assert_(jentry in pubs, "master pub/sub list %s is missing %s"%(pubs, jentry))
00393
00394
00395
00396
00397 self.apiError(master.lookupNode(self.caller_id, caller_id), "master has a stale reference to unregistered topic node API. pubs are %s"%pubs)
00398
00399
00400
00401 def _subTestRegisterSubscriberSimpleSuccess(self):
00402 master = self.master
00403
00404 caller_id = '/sub_node'
00405 caller_api = 'http://localhost:4567/'
00406 topic_base = '/sub_topic'
00407 topic_type = 'test_rosmaster/String'
00408
00409
00410 for i in xrange(0, 10):
00411 topic_name = "%s-%s"%(topic_base, i)
00412
00413 self.apiSuccess(master.registerSubscriber(caller_id, topic_name, topic_type, caller_api))
00414
00415
00416 val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
00417 self.assertEquals(caller_api, val)
00418
00419
00420 val = self.apiSuccess(master.getTopicTypes(self.caller_id))
00421 self.assert_([topic_name, topic_type] in val, "master does not know topic type: %s"%val)
00422
00423 _, subs, _ = self.apiSuccess(master.getSystemState(self.caller_id))
00424 for j in xrange(0, i+1):
00425 jtopic_name = "%s-%s"%(topic_base, j)
00426 jentry = [jtopic_name, [caller_id]]
00427 self.assert_(jentry in subs, "master pub/sub list %s is missing %s"%(subs, jentry))
00428
00429
00430 def _testRegisterSubscriberSimpleSuccess(self):
00431 self._subTestRegisterSubscriberSimpleSuccess()
00432
00433 def _testUnregisterSubscriberSuccess(self):
00434 self._subTestRegisterSubscriberSimpleSuccess()
00435 master = self.master
00436 caller_id = '/sub_node'
00437 caller_api = 'http://localhost:4567/'
00438 topic_base = '/sub_topic'
00439
00440 for i in xrange(0, 10):
00441 topic_name = "%s-%s"%(topic_base, i)
00442
00443
00444 code, msg, val = master.unregisterSubscriber(caller_id, topic_name, caller_api)
00445 self.assertEquals(code, 1, "code != 1, return message was [%s]"%msg)
00446
00447
00448 if i < 9:
00449 val = self.apiSuccess(master.lookupNode(self.caller_id, caller_id))
00450 self.assertEquals(caller_api, val, "master prematurely invalidated node entry for [%s] (lookupNode)"%caller_id)
00451
00452 _, subs, _ = self.apiSuccess(master.getSystemState(self.caller_id))
00453 for j in xrange(0, i+1):
00454 jtopic_name = "%s-%s"%(topic_base, j)
00455 jentry = [jtopic_name, [caller_id]]
00456 self.assert_(jentry not in subs, "master pub/sub list %s should not have %s"%(subs, jentry))
00457 for j in xrange(i+1, 10):
00458 jtopic_name = "%s-%s"%(topic_base, j)
00459 jentry = [jtopic_name, [caller_id]]
00460 self.assert_(jentry in subs, "master pub/sub list %s is missing %s"%(subs, jentry))
00461
00462
00463 self.apiError(master.lookupNode(self.caller_id, caller_id), "master has a stale reference to unregistered topic node API. subs are %s"%subs)
00464
00465