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