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 testMaster: ROS integration test cases for master XML-RPC API
00036
00037 To run, invoke nodes/testMaster
00038 """
00039
00040 import os, sys, getopt, traceback, logging, socket
00041 import datetime, xmlrpclib, math, random
00042 import unittest
00043 import rospy
00044 from test_ros.rostest import *
00045 from test_ros.testSlave import msMain
00046
00047 MYPKG = 'test_ros'
00048
00049 HAS_PARAM = True
00050
00051 singletest = 'testGetFlowNames'
00052 singletest = None
00053
00054
00055 def verifyNodeAddress(master, callerId, name, machine, addr, port):
00056 if not name:
00057 raise Exception("name is None")
00058 rmachine, raddr, rport = apiSuccess(master.getNodeAddress(callerId, name))
00059 if machine:
00060 assert rmachine == machine, "Node [%s] is running on '%s' instead of '%s'"%(name, rmachine, machine)
00061 if port:
00062 assert rport == port, "Node [%s] is running on '%s' instead of '%s'"%(name, rport, port)
00063 else:
00064 assert rport, "Node [%s] does not have a registered port"%name
00065 if addr:
00066 if addr == 'localhost':
00067 addr = socket.gethostname()
00068 if raddr == 'localhost':
00069 raddr = socket.gethostname()
00070 assert socket.gethostbyname(raddr) == socket.gethostbyname(addr), "%s!=%s"%(socket.gethostbyname(raddr), socket.gethostbyname(addr))
00071
00072 apiSuccess(xmlrpclib.ServerProxy("http://%s:%s/"%(raddr, rport)).getPid(''))
00073
00074 def testGraphState(master, graphNodes, graphFlows):
00075 graph = apiSuccess(master.getGraph(''))
00076 diff = set(graph[0]) ^ set(graphNodes)
00077 assert not diff, "Graph nodes %s does not match expected %s: %s"%(graph[0], graphNodes, diff)
00078
00079 expectedFlows = ["%s:%s:1"%f for f in graphFlows]
00080 print graph[1]
00081 remoteFlows = ["%s:%s:%s"%(src,snk,c) for (src,snk,c) in graph[1]]
00082 if expectedFlows or remoteFlows:
00083
00084 diff = set(expectedFlows) ^ set(remoteFlows)
00085 assert not diff, "Graph flows %s does not match expected %s: %s"%(expectedFlows, remoteFlows, diff)
00086
00087 def testParamState(master, myState):
00088 callerId = 'master'
00089 for (k, v) in myState.iteritems():
00090 if HAS_PARAM:
00091 assert apiSuccess(master.hasParam(callerId, k))
00092 print "verifying parameter %s"%k
00093 v2 = apiSuccess(master.getParam(callerId, k))
00094 if isinstance(v2, xmlrpclib.DateTime):
00095 assert xmlrpclib.DateTime(v) == v2, "[%s]: %s != %s, %s"%(k, v, v2, v2.__class__)
00096 else:
00097 assert v == v2, "[%s]: %s != %s, %s"%(k, v, v2, v2.__class__)
00098 paramNames = myState.keys()
00099 remoteParamNames = apiSuccess(master.getParamNames(callerId))
00100 assert not set(paramNames) ^ set(remoteParamNames), "parameter server keys do not match local"
00101
00102 class ParamServerTestCase(ROSGraphTestCase):
00103 """Parameter Server API Test Cases"""
00104
00105 def setUp(self):
00106 super(ParamServerTestCase, self).setUp()
00107
00108 def tearDown(self):
00109 super(ParamServerTestCase, self).tearDown()
00110
00111 def _testSetParam(self, ctx, myState, testVals, master):
00112 for type, vals in testVals:
00113 try:
00114 if ctx:
00115 callerId = "%s.node"%ctx
00116 else:
00117 callerId = "node"
00118 count = 0
00119 for val in vals:
00120 key = "%s-%s"%(type,count)
00121 print "master.setParam(%s,%s,%s)"%(callerId, key, val)
00122 master.setParam(callerId, key, val)
00123 if HAS_PARAM:
00124 assert apiSuccess(master.hasParam(callerId, key))
00125 if ctx:
00126 trueKey = "%s.%s"%(ctx, key)
00127 else:
00128 trueKey = key
00129 myState[trueKey] = val
00130 count += 1
00131 except:
00132 assert "getParam failed on type[%s], val[%s]"%(type,val)
00133 testParamState(master, myState)
00134
00135 def testParamValues(self):
00136 """testParamValues: test storage of all XML-RPC compatible types"""
00137 from xmlrpclib import Binary
00138 testVals = [
00139 ['int', [0, 1024, 2147483647, -2147483647]],
00140 ['boolean', [True, False]],
00141 ['string', ['', '\0', 'x', 'hello', ''.join([chr(n) for n in xrange(0, 255)])]],
00142 ['double', [0.0, math.pi, -math.pi, 3.4028235e+38, -3.4028235e+38]],
00143
00144 ['datetime', [datetime.datetime(2005, 12, 6, 12, 13, 14), datetime.datetime(1492, 12, 6, 12, 13, 14)]],
00145 ['base64', [Binary(''), Binary('\0'), Binary(''.join([chr(n) for n in xrange(0, 255)]))]],
00146 ['struct', [{ "a": 2, "b": 4},
00147 {"a" : "b", "c" : "d"},
00148 {"a" : {"b" : { "c" : "d"}}}]],
00149 ['array', [[], [1, 2, 3], ['a', 'b', 'c'], [0.0, 0.1, 0.2, 2.0, 2.1, -4.0],
00150 [1, 'a', math.pi], [[1, 2, 3], ['a', 'b', 'c'], [1.0, 2.1, 3.2]]]
00151 ],
00152 ]
00153 master = self.master
00154
00155 print "Putting parameters onto the server"
00156
00157 contexts = ['', 'scope1', 'scope2', 'scope.subscope1', 'scope.sub1.sub2']
00158 myState = {}
00159 for ctx in contexts:
00160 self._testSetParam(ctx, myState, testVals, master)
00161
00162 print "Deleting all of our parameters"
00163
00164 paramKeys = myState.keys()
00165 for key in paramKeys:
00166 apiSuccess(master.deleteParam('', key))
00167 del myState[key]
00168 testParamState(master, myState)
00169
00170 def testEncapsulation(self):
00171 """testEncapsulation: test encapsulation: setting same parameter at different levels"""
00172 master = self.master
00173 myState = {}
00174 testParamState(master, myState)
00175
00176 testContexts = ['', 'en', 'en.sub1', 'en.sub2', 'en.sub1.sub2']
00177 for c in testContexts:
00178 testKey = 'param1'
00179 testVal = random.randint(-1000000, 100000)
00180 if c:
00181 callerId = "%s.node"%c
00182 trueKey = "%s.%s"%(c,testKey)
00183 else:
00184 callerId ="node"
00185 trueKey = testKey
00186 master.setParam(callerId, testKey, testVal)
00187 myState[trueKey] = testVal
00188
00189 v1 = apiSuccess(master.getParam('', trueKey))
00190 v2 = apiSuccess(master.getParam(callerId, testKey))
00191 assert v1 == v2, "[%s]: %s vs. [%s,%s]: %s"%(trueKey, v1, callerId, testKey, v2)
00192 if HAS_PARAM:
00193 assert apiSuccess(master.hasParam(callerId, testKey)), testKey
00194 assert apiSuccess(master.hasParam('node', trueKey)), trueKey
00195
00196 testParamState(master, myState)
00197
00198 def testDotLocalNames(self):
00199 master = self.master
00200 myState = {}
00201 testParamState(master, myState)
00202
00203 testContexts = ['', 'sub1', 'sub1.sub2', 'sub1.sub2.sub3']
00204 for c in testContexts:
00205 if c:
00206 callerId = "%s.node"%c
00207 else:
00208 callerId = "node"
00209 testKey = ".param1"
00210 testVal = random.randint(-1000000, 100000)
00211 master.setParam(callerId, testKey, testVal)
00212 trueKey = callerId+testKey
00213 myState[trueKey] = testVal
00214
00215 v1 = apiSuccess(master.getParam('node', trueKey))
00216 v2 = apiSuccess(master.getParam(callerId, testKey))
00217 assert v1 == v2, "[%s]: %s vs. [%s,%s]: %s"%(trueKey, v1, callerId, testKey, v2)
00218 if HAS_PARAM:
00219 assert apiSuccess(master.hasParam(callerId, testKey)), testKey
00220 assert apiSuccess(master.hasParam('node', trueKey)), trueKey
00221
00222
00223 testKey = "altnode.param2"
00224 testVal = random.randint(-1000000, 100000)
00225 master.setParam(callerId, testKey, testVal)
00226 if c:
00227 trueKey = "%s.%s"%(c,testKey)
00228 altCallerId = "%s.altnode"%c
00229 else:
00230 trueKey = testKey
00231 altCallerId = "altnode"
00232 myState[trueKey] = testVal
00233
00234 v1 = apiSuccess(master.getParam(altCallerId, ".param2"))
00235 v2 = apiSuccess(master.getParam(callerId, testKey))
00236 assert v1 == v2
00237 if HAS_PARAM:
00238 assert apiSuccess(master.hasParam(callerId, testKey)), testKey
00239 assert apiSuccess(master.hasParam(altCallerId, ".param2"))
00240
00241 testParamState(master, myState)
00242
00243 def testScopeUp(self):
00244 """testScopeUp: test that parameter server can chain up scopes to find/delete parameters"""
00245 master = self.master
00246 myState = {}
00247 testParamState(master, myState)
00248
00249 testVal = random.randint(-1000000, 100000)
00250 master.setParam('', 'uparam1', testVal)
00251 myState['uparam1'] = testVal
00252 assert testVal == apiSuccess(master.getParam('node', 'uparam1'))
00253 assert testVal == apiSuccess(master.getParam('uptest.node', 'uparam1'))
00254 assert testVal == apiSuccess(master.getParam('uptest.sub1.node', 'uparam1'))
00255 assert testVal == apiSuccess(master.getParam('uptest.sub1.sub2.node', 'uparam1'))
00256
00257 testVal = random.randint(-1000000, 100000)
00258 master.setParam('uptest2.sub1.node', 'uparam2', testVal)
00259 myState['uptest2.sub1.uparam2'] = testVal
00260 assert testVal == apiSuccess(master.getParam('uptest2.sub1.node', 'uparam2'))
00261 assert testVal == apiSuccess(master.getParam('uptest2.sub1.sub2.node', 'uparam2'))
00262 assert testVal == apiSuccess(master.getParam('uptest2.sub1.sub2.sub3.node', 'uparam2'))
00263 testParamState(master, myState)
00264
00265
00266 apiSuccess(master.deleteParam('uptest.sub1.sub2.node', 'uparam1'))
00267 del myState['uparam1']
00268 testParamState(master, myState)
00269 apiSuccess(master.deleteParam('uptest2.sub1.sub2.sub3.node', 'uparam2'))
00270 del myState['uptest2.sub1.uparam2']
00271 testParamState(master, myState)
00272
00273 def testScopeDown(self):
00274 """testScopeDown: test scoping rules for sub contexts"""
00275 master = self.master
00276 myState = {}
00277 testParamState(master, myState)
00278
00279
00280 testVal = random.randint(-1000000, 100000)
00281 master.setParam('down.one.two.three.node', 'dparam1', testVal)
00282 myState['down.one.two.three.dparam1'] = testVal
00283 if HAS_PARAM:
00284 assert not apiSuccess(master.hasParam('down.one', 'dparam1'))
00285 assert not apiSuccess(master.hasParam('down.one.two', 'dparam1'))
00286 apiError(master.getParam('down.one.node', 'dparam1'))
00287 apiError(master.getParam('down.one.two.node', 'dparam1'))
00288
00289
00290 testVal = random.randint(-1000000, 100000)
00291 master.setParam('node', 'down2.dparam2', testVal)
00292 myState['down2.dparam2'] = testVal
00293 assert testVal == apiSuccess(master.getParam('down2.node', 'dparam2'))
00294 assert testVal == apiSuccess(master.getParam('', 'down2.dparam2'))
00295 if HAS_PARAM:
00296 assert not apiSuccess(master.hasParam('down2.node', 'down2.dparam2'))
00297 apiError(master.getParam('down2.node', 'down2.dparam2'))
00298 testParamState(master, myState)
00299
00300
00301 testVal = random.randint(-1000000, 100000)
00302 master.setParam('node', 'down3.sub.dparam3', testVal)
00303 myState['down3.sub.dparam3'] = testVal
00304 assert testVal == apiSuccess(master.getParam('down3.sub.node', 'dparam3'))
00305 assert testVal == apiSuccess(master.getParam('down3.node', 'sub.dparam3'))
00306 assert testVal == apiSuccess(master.getParam('', 'down3.sub.dparam3'))
00307 assert testVal == apiSuccess(master.getParam('down3.sub.sub2.node', 'dparam3'))
00308 if HAS_PARAM:
00309 assert not apiSuccess(master.hasParam('down3.sub.node', 'sub.dparam3'))
00310 assert not apiSuccess(master.hasParam('down3.sub.node', 'down3.sub.dparam3'))
00311 apiError(master.getParam('down3.sub.node', 'sub.dparam3'))
00312 apiError(master.getParam('down3.sub.node', 'down3.sub.dparam3'))
00313 testParamState(master, myState)
00314
00315
00316 master.setParam('node', 'down4.sub.dparam4A', testVal)
00317 apiSuccess(master.deleteParam('down4.sub.node', 'dparam4A'))
00318 if HAS_PARAM:
00319 assert not apiSuccess(master.hasParam('down4.sub', 'dparam4A'))
00320 master.setParam('node', 'down4.sub.dparam4B', testVal)
00321 apiSuccess(master.deleteParam('down4.node', 'sub.dparam4B'))
00322 if HAS_PARAM:
00323 assert not apiSuccess(master.hasParam('down4.sub', 'dparam4B'))
00324 master.setParam('node', 'down4.sub.dparam4C', testVal)
00325 apiSuccess(master.deleteParam('', 'down4.sub.dparam4C'))
00326 if HAS_PARAM:
00327 assert not apiSuccess(master.hasParam('down4.sub.node', 'dparam4C'))
00328 testParamState(master, myState)
00329
00330 class MasterTestCase(ROSGraphTestCase):
00331 """Master API Test Cases -- those not covered by ParamServer and AddKillNode"""
00332
00333 def setUp(self):
00334 super(MasterTestCase, self).setUp()
00335
00336 def tearDown(self):
00337 super(MasterTestCase, self).tearDown()
00338
00339 def _verifyFlowNameState(self, master, state):
00340 flows = apiSuccess(master.getFlowNames('node1', ''))
00341 assert len(flows) == len(state.values()), "Master reported a different number of flows"
00342 for val in state.itervalues():
00343 assert val in flows, "flows does not contain %s : %s"%(val, flows)
00344
00345 def testPromoteFlow(self):
00346 master = self.master
00347 state = {}
00348 callerId = 'node1'
00349 type = 'common_flows/String'
00350
00351 apiSuccess(master.registerNode(callerId, 'node1', 'localhost', 1234, []))
00352 for i in range(1, 4):
00353 for dir in ['inflow', 'outflow']:
00354 locator = 'node1:%s%s'%(dir, i)
00355 apiSuccess(master.registerFlow(callerId, 'node1', locator, dir, type))
00356 state[locator] = [locator, dir, type, 0]
00357
00358
00359 apiError(master.promoteFlow(callerId, 'node1:notAFlow', 'node1:newNotAFlow'))
00360
00361 apiError(master.promoteFlow(callerId, ':outflow1', 'node1:newNotAFlow'))
00362
00363
00364
00365 dir = 'outflow'
00366 apiSuccess(master.promoteFlow(callerId, 'node1:outflow1', ':outflow1'))
00367 state[':outflow1'] = [':outflow1', dir, type, 1]
00368
00369 apiSuccess(master.promoteFlow(callerId, '.:outflow2', ':outflow2'))
00370 state[':outflow2'] = [':outflow2', dir, type, 1]
00371
00372
00373
00374 dir = 'inflow'
00375 tests = [
00376 ['node1:inflow1', 'node1:newInflow1'],
00377 ['node1:inflow2', 'sibling:inflow2'],
00378 ['node1:inflow3', 'node1:subgraph1:inflow3']
00379 ]
00380 for source, target in tests:
00381 apiSuccess(master.promoteFlow(callerId, source, target))
00382 state[target] = [target, dir, type, 1]
00383
00384 self._verifyFlowNameState(master, state)
00385
00386
00387 apiError(master.promoteFlow(callerId, 'node1:outflow1', 'node1:outflow2'))
00388 apiError(master.promoteFlow(callerId, 'node1:outflow2', ':outflow1'))
00389 apiError(master.promoteFlow(callerId, 'node1:inflow1', 'sibling:inflow2'))
00390
00391
00392
00393
00394
00395 def testRegisterFlow(self):
00396 master = self.master
00397 state = {}
00398 type = 'common_flows/String'
00399 for callerId in ['node1', 'subgraph.node1', 'grandparent.parent.node1']:
00400
00401 apiSuccess(master.registerNode(callerId, 'node1', 'localhost', 1234, []))
00402 for i in range(1, 4):
00403 for dir in ['inflow', 'outflow']:
00404 if dir == 'inflow':
00405 locator = 'node1:%s%s'%(dir, i)
00406 else:
00407 locator = '.:%s%s'%(dir, i)
00408 apiSuccess(master.registerFlow(callerId, 'node1', locator, dir, type))
00409 realLocator = '%s:%s%s'%(callerId, dir, i)
00410 state[realLocator] = [realLocator, dir, type, 0]
00411
00412 apiError(master.registerFlow(callerId, 'notNode', 'notANode:outflow', 'outflow', type))
00413
00414 apiError(master.registerFlow(callerId, 'node1', '', 'outflow', type))
00415 apiError(master.registerFlow(callerId, 'node1', 'badflow1', 'outflow', type))
00416
00417 apiError(master.registerFlow(callerId, 'node1', 'node1:badflow2', 'spiralflow', type))
00418
00419 apiError(master.registerFlow(callerId, 'node1', 'node1:badflow3', 'outflow', ''))
00420 apiError(master.registerFlow(callerId, 'node1', 'node1:badflow4', 'outflow', 'faketype'))
00421
00422
00423 apiError(master.registerFlow(callerId, 'node1', 'node1:outflow1', 'outflow', type))
00424 apiSuccess(master.promoteFlow(callerId, 'node1:outflow1', 'node1:newOutflow1'))
00425 state['%s:newOutflow1'%callerId] = ['node1:newOutflow1', dir, type, 1]
00426 apiError(master.registerFlow(callerId, 'node1', 'node1:newOutflow1', 'outflow', type))
00427
00428 self._verifyFlowNameState(master, state)
00429
00430 def testUnregisterFlow(self):
00431 master = self.master
00432 state = {}
00433 type = 'common_flows/String'
00434 for callerId in ['node1', 'subgraph.node1', 'grandparent.parent.node1']:
00435
00436 apiSuccess(master.registerNode(callerId, 'node1', 'localhost', 1234, []))
00437 for i in range(1, 4):
00438 for dir in ['inflow', 'outflow']:
00439 if dir == 'inflow':
00440 locator = rlocator = 'node1:%s%s'%(dir, i)
00441 else:
00442 locator = '.:%s%s'%(dir, i)
00443 rlocator = 'node1:%s%s'%(dir, i)
00444 apiSuccess(master.registerFlow(callerId, 'node1', locator, dir, type))
00445 realLocator = '%s:%s%s'%(callerId, dir, i)
00446 state[realLocator] = [realLocator, dir, type, 0]
00447
00448 self._verifyFlowNameState(master, state)
00449
00450
00451 apiError(master.unregisterFlow(callerId, 'notANode:outflow'))
00452 apiError(master.unregisterFlow(callerId, ''))
00453 apiError(master.unregisterFlow(callerId.replace('node1', 'node2'), 'outflow1'))
00454
00455 apiSuccess(master.unregisterFlow(callerId, 'node1:outflow1'))
00456 del state['%s:outflow1'%callerId]
00457 apiSuccess(master.unregisterFlow(callerId, '.:outflow2'))
00458 del state['%s:outflow2'%callerId]
00459 apiSuccess(master.unregisterFlow(callerId.replace('node1', 'node2'), 'node1:outflow3'))
00460 del state['%s:outflow3'%callerId]
00461 apiSuccess(master.unregisterFlow('master', '%s:inflow1'%callerId))
00462 del state['%s:inflow1'%callerId]
00463
00464 self._verifyFlowNameState(master, state)
00465
00466
00467 apiError(master.unregisterFlow(callerId, 'node1:outflow1'))
00468
00469
00470 apiSuccess(master.promoteFlow(callerId, 'node1:inflow3', ':inflow3A'))
00471 apiSuccess(master.promoteFlow(callerId, ':inflow3A', ':inflow3B'))
00472
00473 apiSuccess(master.unregisterFlow(callerId, 'node1:inflow3'))
00474 del state['%s:inflow3'%callerId]
00475
00476 self._verifyFlowNameState(master, state)
00477
00478 def testGetFlowNames(self):
00479 master = self.master
00480 pkg,node = testNode
00481 subgraph = 'sub1.sub2'
00482 name = 'testGFN_A'
00483 port = apiSuccess(master.addNode('caller', subgraph, name, pkg, node, TEST_MACHINE, 0))
00484
00485
00486 testFlowNames = ["%s:%s"%(name, v) for v in ["in", "out"]]
00487 print "FLOW NAMES", apiSuccess(master.getFlowNames('master', ''))
00488 flows = apiSuccess(master.getFlowNames('%s.caller'%subgraph, ''))
00489 assert not set([x[0] for x in flows]) ^ set(testFlowNames), "%s vs. %s"%([x[0] for x in flows], testFlowNames)
00490
00491 inDirs = [x[1] for x in flows if x[0].endswith(':in')]
00492 outDirs = [x[1] for x in flows if x[0].endswith(':out')]
00493 assert not filter(lambda x: x != "inflow", inDirs), inDirs
00494 assert not filter(lambda x: x != "outflow", outDirs), outDirs
00495 assert not filter(lambda x: x != "common_flows/String", [x[2] for x in flows])
00496 assert not filter(lambda x: x, [x[3] for x in flows])
00497
00498
00499 testFlowNames = ["%s.%s:%s"%(subgraph, name, v) for v in ["in", "out"]]
00500 flows = apiSuccess(master.getFlowNames('caller', subgraph))
00501 assert not set([x[0] for x in flows]) ^ set(testFlowNames), "%s vs. %s"%([x[0] for x in flows], testFlowNames)
00502 flows = apiSuccess(master.getFlowNames('caller', "%s.%s"%(subgraph, name)))
00503 assert not set([x[0] for x in flows]) ^ set(testFlowNames), "%s vs. %s"%([x[0] for x in flows], testFlowNames)
00504
00505 testFlowNames = ["sub2.%s:%s"%(name, v) for v in ["in", "out"]]
00506 flows = apiSuccess(master.getFlowNames('sub1.caller', 'sub2'))
00507 assert not set([x[0] for x in flows]) ^ set(testFlowNames), "%s vs. %s"%([x[0] for x in flows], testFlowNames)
00508
00509
00510 testFlowNames = ["%s.%s:%s"%(subgraph, name, v) for v in ["in", "out"]]
00511 flows = apiSuccess(master.getFlowNames('caller', ''))
00512 flowNames = [x[0] for x in flows]
00513 assert not set(flowNames) ^ set(testFlowNames)
00514
00515
00516 def testGetNodeAddress(self):
00517 def validate(val, callerId, name, port):
00518 assert len(val) == 3, "getNodeAddress did not return 3-element list for value field"
00519 assert type(val[0]) == str and type(val[1]) == str and type(val[2]) == int,\
00520 "getNodeAddress did not return (str, str, int) for value field"
00521 verifyNodeAddress(master, callerId, name, TEST_MACHINE, 'localhost', port)
00522
00523
00524
00525
00526
00527 master = self.master
00528
00529 code, msg, val = master.getNodeAddress('', 'testGetNodeAddress-fake')
00530 assert code == -1, "getNodeAddress did not return failure code 0 for non-existent node"
00531 assert len(val) == 3, "getNodeAddress did not return 3-element list for value field in error case"
00532 assert type(val[0]) == str and type(val[1]) == str and type(val[2]) == int,\
00533 "getNodeAddress did not return (str, str, int) for value field in error case"
00534
00535
00536 name = 'testGetNodeAddress-1'
00537 port = 7981
00538 pkg, node = testNode
00539 apiSuccess(master.addNode('', '', name, pkg, node, TEST_MACHINE, port))
00540 val = apiSuccess(master.getNodeAddress('', name))
00541 validate(val, '', name, port)
00542
00543
00544 name = 'testGetNodeAddress-2'
00545 port = 7982
00546 apiSuccess(master.addNode('', 'gna1.gna2', name, pkg, node, TEST_MACHINE, port))
00547
00548 tests = [
00549
00550 ['gna1.gna2.node', name],
00551 ['gna1.node', 'gna2.%s'%name],
00552 ['', 'gna1.gna2.%s'%name],
00553
00554 ['gna1.gna2.gna3.node', name],
00555 ]
00556 for test in tests:
00557 callerId, name = test
00558 validate(apiSuccess(master.getNodeAddress(callerId, name)), callerId, name, port)
00559
00560
00561 val = apiError(master.getNodeAddress('gna1.gna2', 'gna3.%s'%name))
00562
00563 def _verifyNodeDead(self, port):
00564 testUri = "http://localhost:%s/"%port
00565 try:
00566 xmlrpclib.ServerProxy(testUri).getPid('node')
00567 self.fail("test node is still running")
00568 except:
00569 pass
00570
00571 def testAddKillNode(self):
00572 """testAddKillNode: test adding then killing nodes"""
00573
00574 master = self.master
00575 pkg,node = testNode
00576 apiError(master.killNode('node','nonexistentNode'))
00577 name = 'testAddKillA'
00578 port = apiSuccess(master.addNode('node', 'subgraph', name, pkg, node, TEST_MACHINE, 0))
00579
00580 apiError(master.killNode('different.subgraph.node', name))
00581
00582 apiError(master.killNode('node', name))
00583
00584 apiError(master.killNode('subgraph.sub2.node', name))
00585
00586 apiSuccess(master.killNode('subgraph.node', name))
00587
00588
00589 tests = [['node', '', 'testAddKillB'],
00590 ['node', 'g1.g2', 'testAddKillB'],
00591 ['node', 'g1', 'testAddKillB'],
00592 ['g1.g2.node', 'g3', 'testAddKillB'],
00593 ]
00594 for callerId, subcontext, nodeName in tests:
00595 port = apiSuccess(master.addNode(callerId, subcontext, nodeName, pkg, node, TEST_MACHINE, 0))
00596 if subcontext:
00597 name = "%s.%s"%(subcontext, nodeName)
00598 else:
00599 name = nodeName
00600 apiSuccess(master.killNode(callerId, name))
00601 self._verifyNodeDead(port)
00602
00603 def testAddNode(self):
00604 """testAddNode: test master.addNode(callerId, subcontext, name, pkg, pkgNode, machine, port)"""
00605 master = self.master
00606 graphNodes = ['master']
00607 graphFlows = []
00608
00609 pkg, node = testNode
00610 errors = [
00611
00612 ['', 12, 'testAddNodeError1', pkg, node, TEST_MACHINE, 0],
00613
00614 ['', '', 123, pkg, node, TEST_MACHINE, 0],
00615
00616 ['', '', 'testAddNodeError2', 123, node, TEST_MACHINE, 0],
00617
00618 ['', '', 'testAddNodeError3', pkg, '', TEST_MACHINE, 0],
00619 ['', '', 'testAddNodeError4', pkg, 123, TEST_MACHINE, 0],
00620
00621 ['', '', 'testAddNodeError6', pkg, node, 'unknown', 0],
00622 ['', '', 'testAddNodeError7', pkg, 'noNode', 123, 0],
00623
00624 ['', '', 'testAddNodeError8', pkg, node, TEST_MACHINE, -80],
00625 ['', '', 'testAddNodeError9', pkg, node, TEST_MACHINE, "80"],
00626 ]
00627 for args in errors:
00628 try:
00629 apiError(master.addNode(*args))
00630 except Exception, e:
00631 self.fail("addNodeError case failed with args[%s] and exception [%s]"%(args, e))
00632
00633 apiFail(master.addNode('', '', 'testAddNodeFail1', pkg, 'notANode', TEST_MACHINE, 0))
00634
00635 testGraphState(master, graphNodes, graphFlows)
00636 tests = [[['','testAddNode1'], [TEST_MACHINE, 7980]],
00637 [['','testAddNode2'], [TEST_MACHINE, 0]],
00638 [['','testAddNode3'], ['', 0]],
00639 [['','testAddNode4'], [TEST_MACHINE, 0]],
00640 [['','testAddNode5'], [TEST_MACHINE, 0]],
00641 [['','testAddNode6'], [TEST_MACHINE, 0]],
00642 [['','testAddNode7'], [TEST_MACHINE, 0]],
00643
00644 [['push', 'testAddNode8'], [TEST_MACHINE, 0]],
00645 [['push.one.two', 'testAddNode9'], [TEST_MACHINE, 0]],
00646 [['stanford.addNodeTest','testAddNodeA'], [TEST_MACHINE, 0]],
00647 [['wg.addNodeTest', 'testAddNodeA'], [TEST_MACHINE, 0]],
00648 ]
00649 for fullname, args in tests:
00650 print "testAddNode: testing", fullname
00651 subcontext, name = fullname
00652 if subcontext:
00653 fullname = '%s.%s'%(subcontext, name)
00654 else:
00655 fullname = name
00656 machine, port = args
00657 apiSuccess(master.addNode('', subcontext, name, pkg, node, machine, port))
00658 verifyNodeAddress(master, '', fullname, machine, 'localhost', port)
00659 graphNodes.append(fullname)
00660 testGraphState(master, graphNodes, graphFlows)
00661
00662 apiSuccess(master.addNode('', subcontext, name, pkg, node, machine, port))
00663
00664
00665
00666
00667 port = apiSuccess(master.addNode('node', 'duplicate.test', 'nodeA', pkg, node, TEST_MACHINE, 0))
00668 apiError(master.addNode('node', 'duplicate.test', 'nodeA', pkg, node, TEST_MACHINE, port + 1))
00669 apiError(master.addNode('node', 'duplicate.test', 'nodeA', pkg+'foo', node, TEST_MACHINE, port))
00670 apiError(master.addNode('node', 'duplicate.test', 'nodeA', pkg, node+'foo', TEST_MACHINE, port))
00671
00672
00673 def testGetGraph(self):
00674
00675
00676 pass
00677
00678 def testAddMachine(self):
00679 master = self.master
00680 host, port = masterAddr
00681
00682
00683 apiError(master.addMachine('node', '', self.rosRoot, host, 22, '', ''))
00684 apiError(master.addMachine('node', 123, self.rosRoot, host, 22, '', ''))
00685
00686 apiError(master.addMachine('node', 'name', '', host, 22, '', ''))
00687 apiError(master.addMachine('node', 'name', 123, host, 22, '', ''))
00688
00689 apiError(master.addMachine('node', 'name', '', '', 22, '', ''))
00690 apiError(master.addMachine('node', 'name', '', 123, 22, '', ''))
00691
00692 apiError(master.addMachine('node', 'name', '', host, -22, '', ''))
00693 apiError(master.addMachine('node', 'name', '', host, "22", '', ''))
00694
00695 tests = [
00696 ['node', 'testAddMachine-1'],
00697 ['g1.node', 'testAddMachine-2'],
00698 ['g1.g2.g3.node', 'testAddMachine-3'],
00699 ['g1.g2.node', 'testAddMachine-4'],
00700 ]
00701 rosRoot = self.rosRoot
00702 for callerId, m in tests:
00703 apiSuccess(master.addMachine(callerId, m, rosRoot, host, 22, '', ''))
00704
00705 apiSuccess(master.addMachine(callerId, m, rosRoot, host, 22, '', ''))
00706
00707 apiError(master.addMachine(callerId, m, rosRoot+'/foo/', host, 22, '', ''))
00708 apiError(master.addMachine(callerId, m, rosRoot, 'www.google.com', 22, '', ''))
00709 apiError(master.addMachine(callerId, m, rosRoot, host, 21, '', ''))
00710 apiError(master.addMachine(callerId, m, rosRoot, host, 22, 'fake-user', ''))
00711 apiError(master.addMachine(callerId, m, rosRoot, host, 22, '', 'fake-password'))
00712
00713
00714
00715 def testRegisterNode_Flows(self):
00716
00717 pass
00718
00719 def testRegisterNode(self):
00720 master = self.master
00721 flows = []
00722
00723 apiError(master.registerNode('', '', 'localhost', 80, flows))
00724
00725 apiError(master.registerNode('', 'registerNodeFail2', '', 80, flows))
00726
00727 apiError(master.registerNode('', 'registerNodeFail3', 'localhost', -80, flows))
00728 apiError(master.registerNode('', 'registerNodeFail4', 'localhost', 0, flows))
00729
00730
00731
00732
00733
00734 testCases = [
00735 ['', 'registerNodeExternal-1'],
00736 ['', 'rne.registerNodeExternal-2'],
00737 ['rne', 'registerNodeExternal-3'],
00738 ['', 'rne.rne2.rne3.registerNodeExternal-4'],
00739 ['rne', 'rne2.rne3.registerNodeExternal-5'],
00740 ['rne.rne2.rne3', 'registerNodeExternal-6'],
00741 ]
00742 for context, name in testCases:
00743 try:
00744 if context:
00745 fullName = "%s.%s"%(context, name)
00746 callerId = "%s.node"%context
00747 else:
00748 fullName = name
00749 callerId = "node"
00750 startTestNode(fullName)
00751
00752
00753 timeoutT = time.time() + 4.0
00754 node = getTestNode()
00755 val = None
00756 while time.time() < timeoutT and not val:
00757 try:
00758 _, _, val = node.getPid('')
00759 except:
00760 pass
00761 assert val, "unable to start test node for registerNode test case"
00762
00763 verifyNodeAddress(master, callerId, name, None, testNodeAddr[0], testNodeAddr[1])
00764 finally:
00765 stopTestNode()
00766
00767 def testConnectFlow(self):
00768 master = self.master
00769 pkg, node = testNode
00770 graphNodes = ['master']
00771 graphFlows = []
00772 machine = TEST_MACHINE
00773 for i in range(1, 5):
00774 apiSuccess(master.addNode('m', '', 'baseTcfNode-%s'%i, pkg, node, machine, 0))
00775 graphNodes.append('baseTcfNode-%s'%i)
00776 apiSuccess(master.addNode('m', '', 'tcfNode-%s'%i, pkg, node, machine, 0))
00777 graphNodes.append('tcfNode-%s'%i)
00778 apiSuccess(master.addNode('m', 'tcf1', 'tcfNode-%s'%i, pkg, node, machine, 0))
00779 graphNodes.append('tcf1.tcfNode-%s'%i)
00780 apiSuccess(master.addNode('m', 'tcf2', 'tcfNode-%s'%i, pkg, node, machine, 0))
00781 graphNodes.append('tcf2.tcfNode-%s'%i)
00782 apiSuccess(master.addNode('m', 'tcf1.sub1', 'tcfNode-%s'%i, pkg, node, machine, 0))
00783 graphNodes.append('tcf1.sub1.tcfNode-%s'%i)
00784 apiSuccess(master.addNode('m', 'tcf2.sub1', 'tcfNode-%s'%i, pkg, node, machine, 0))
00785 graphNodes.append('tcf2.sub1.tcfNode-%s'%i)
00786 apiSuccess(master.addNode('m', 'tcf3', 'tcfNode3-%s'%i, pkg, node, machine, 0))
00787 graphNodes.append('tcf3.tcfNode3-%s'%i)
00788 testGraphState(master, graphNodes, graphFlows)
00789
00790 reliable = 1
00791
00792
00793 illegal = [
00794
00795 ['node.tcf1', 'baseTcfNode-1:out', 'tcfNode-1:in'],
00796 ['tcf1.node', 'tcfNode-1:out', 'baseTcfNode-1:in'],
00797 ['tcf1.tcfNode-1', 'tcfNode-1:out', 'tcf1.tcfNode-1:in'],
00798 ['tcf1.tcfNode-1', ':out', 'tcf1.tcfNode-1:in'],
00799 ['tcf1.tcfNode-1', 'tcf1.tcfNode-2:out', ':in'],
00800 ['tcf1.node', 'tcf1.tcfNode-1:out', 'tcfNode-1:in'],
00801 ['tcf1.node', 'tcf2.tcfNode-1:out', 'tcfNode-1:in'],
00802 ['tcf1.node', 'tcfNode-1:out', 'tcf2.tcfNode-1:in'],
00803 ['tcf1.node', 'sub1.tcfNode-1:out', 'tcf2.sub1.tcfNode-1:in'],
00804 ['tcf1.sub1.node','baseTcfNode-1:out', 'tcfNode-1:in'],
00805 ['tcf1.sub1.node','sub1.tcfNode-1:out', 'tcfNode-1:in'],
00806 ['tcf1.sub1.node','tcf2.tcfNode-1:out', 'tcfNode-1:in'],
00807 ]
00808 for callerId, source, sink in illegal:
00809 apiError(master.connectFlow(callerId, source, sink, reliable))
00810
00811
00812 singleCase = [
00813
00814 ['node', 'tcfNode-1:out', 'tcfNode-2:in', 'tcfNode-1:out', 'tcfNode-2:in',],
00815 ['tcfNode-1','tcf1.tcfNode-1:out', 'tcf1.tcfNode-2:in', 'tcf1.tcfNode-1:out', 'tcf1.tcfNode-2:in'],
00816 ['tcf2.tcfNode-1', 'tcfNode-1:out', 'tcfNode-2:in', 'tcf2.tcfNode-1:out', 'tcf2.tcfNode-2:in'],
00817 ['tcf1.tcfNode-2', 'sub1.tcfNode-1:out', 'sub1.tcfNode-2:in', 'tcf1.sub1.tcfNode-1:out', 'tcf1.sub1.tcfNode-2:in'],
00818 ['tcf2.tcfNode-1', 'tcfNode-1:out', 'sub1.tcfNode-1:in', 'tcf2.tcfNode-1:out', 'tcf2.sub1.tcfNode-1:in'],
00819
00820
00821 ['tcf2.sub1.tcfNode-1', '.:out', 'tcfNode-2:in', 'tcf2.sub1.tcfNode-1:out', 'tcf2.sub1.tcfNode-2:in'],
00822 ['tcf3.tcfNode3-2', 'tcfNode3-1:out', '.:in', 'tcf3.tcfNode3-1:out', 'tcf3.tcfNode3-2:in'],
00823 ]
00824 for callerId, source, sink, sourceFull, sinkFull in singleCase:
00825 apiSuccess(master.connectFlow(callerId, source, sink, reliable))
00826 graphFlows.append((sourceFull, sinkFull))
00827 testGraphState(master, graphNodes, graphFlows)
00828
00829
00830
00831 apiError(master.connectFlow('tcf2.node', 'tcfNode-1:out', 'tcfNode-2:in', reliable))
00832 apiError(master.connectFlow('node', 'tcf1.tcfNode-1:out', 'tcf1.tcfNode-2:in', reliable))
00833
00834
00835
00836
00837
00838 def testKillFlow(self):
00839 master = self.master
00840 if 0:
00841 master.killFlow(callerId, source, sink)
00842
00843 def testMisc(self):
00844 master = self.master
00845 assert master is not None, "master is None"
00846 masterUri = apiSuccess(master.getMasterUri(''))
00847 assert masterUri == apiSuccess(master.getMasterUri('a.different.id')), master.getMasterUri('a.different.id')
00848 assert (getMasterUri() == masterUri) or \
00849 (getMasterUriAlt() == masterUri), masterUri
00850
00851 pid = apiSuccess(master.getPid(''))
00852 assert pid == apiSuccess(master.getPid('a.different.id')), master.getPid('a.different.id')
00853
00854 apiError(master.getPid(0))
00855 apiError(master.getMasterUri(0))
00856
00857 try:
00858 master.shutdown('some.id')
00859 except:
00860 pass
00861 time.sleep(0.1)
00862 try:
00863 code, status, val = master.getPid('')
00864 assert code < 1, "Master is still running after shutdown"
00865 except:
00866 pass
00867
00868 def testMasterMain(argv, stdout, env):
00869 return msMain(argv, stdout, env, [ParamServerTestCase, MasterTestCase], singletest)
00870
00871 if __name__ == '__main__':
00872 testMasterMain(sys.argv, sys.stdout, os.environ)
00873
00874