|
@@ -569,86 +569,152 @@ class TestSystemNamespaceRPCInterface(unittest.TestCase):
|
|
|
inst = self._makeOne([('ns1', ns1)])
|
|
|
self.assertRaises(RPCError, inst.methodSignature, 'ns1.foo')
|
|
|
|
|
|
- def test_multicall_recursion_forbidden(self):
|
|
|
+ def test_multicall_faults_for_recursion(self):
|
|
|
+ from supervisor.xmlrpc import Faults
|
|
|
inst = self._makeOne()
|
|
|
- call = {'methodName':'system.multicall'}
|
|
|
- multiproduce = inst.multicall([call])
|
|
|
- result = multiproduce()
|
|
|
+ calls = [{'methodName':'system.multicall'}]
|
|
|
+ results = inst.multicall(calls)
|
|
|
self.assertEqual(
|
|
|
- result,
|
|
|
- [{'faultCode': 2, 'faultString': 'INCORRECT_PARAMETERS'}]
|
|
|
+ results,
|
|
|
+ [{'faultCode': Faults.INCORRECT_PARAMETERS,
|
|
|
+ 'faultString': ('INCORRECT_PARAMETERS: Recursive '
|
|
|
+ 'system.multicall forbidden')}]
|
|
|
)
|
|
|
|
|
|
- def test_multicall_other_exception(self):
|
|
|
+ def test_multicall_faults_for_missing_methodName(self):
|
|
|
+ from supervisor.xmlrpc import Faults
|
|
|
inst = self._makeOne()
|
|
|
- call = {} # no methodName
|
|
|
- multiproduce = inst.multicall([call])
|
|
|
- result = multiproduce()
|
|
|
- self.assertEqual(len(result), 1)
|
|
|
- self.assertEqual(result[0]['faultCode'], 1)
|
|
|
+ calls = [{}]
|
|
|
+ results = inst.multicall(calls)
|
|
|
+ self.assertEqual(
|
|
|
+ results,
|
|
|
+ [{'faultCode': Faults.INCORRECT_PARAMETERS,
|
|
|
+ 'faultString': 'INCORRECT_PARAMETERS: No methodName'}]
|
|
|
+ )
|
|
|
|
|
|
- def test_multicall_no_calls(self):
|
|
|
+ def test_multicall_faults_for_methodName_bad_namespace(self):
|
|
|
+ from supervisor.xmlrpc import Faults
|
|
|
inst = self._makeOne()
|
|
|
- multiproduce = inst.multicall([])
|
|
|
- result = multiproduce()
|
|
|
- self.assertEqual(result, [])
|
|
|
+ calls = [{'methodName': 'bad.stopProcess'}]
|
|
|
+ results = inst.multicall(calls)
|
|
|
+ self.assertEqual(
|
|
|
+ results,
|
|
|
+ [{'faultCode': Faults.UNKNOWN_METHOD,
|
|
|
+ 'faultString': 'UNKNOWN_METHOD'}]
|
|
|
+ )
|
|
|
|
|
|
- def test_multicall_callback_raises_RPCError(self):
|
|
|
- from supervisor.xmlrpc import RPCError, Faults
|
|
|
+ def test_multicall_faults_for_methodName_good_ns_bad_method(self):
|
|
|
+ from supervisor.xmlrpc import Faults
|
|
|
class DummyNamespace(object):
|
|
|
- def foo(self):
|
|
|
- """ @param string name The thing"""
|
|
|
- raise RPCError(Faults.UNKNOWN_METHOD)
|
|
|
-
|
|
|
+ pass
|
|
|
ns1 = DummyNamespace()
|
|
|
inst = self._makeOne([('ns1', ns1)])
|
|
|
- multiproduce = inst.multicall([{'methodName':'ns1.foo'}])
|
|
|
- result = multiproduce()
|
|
|
+ calls = [{'methodName': 'ns1.bad'}]
|
|
|
+ results = inst.multicall(calls)
|
|
|
self.assertEqual(
|
|
|
- result, [{'faultString': 'UNKNOWN_METHOD', 'faultCode': 1}]
|
|
|
+ results,
|
|
|
+ [{'faultCode': Faults.UNKNOWN_METHOD,
|
|
|
+ 'faultString': 'UNKNOWN_METHOD'}]
|
|
|
)
|
|
|
|
|
|
- def test_multicall_callback_returns_function_returns_NOT_DONE_YET(self):
|
|
|
+ def test_multicall_returns_empty_results_for_empty_calls(self):
|
|
|
+ inst = self._makeOne()
|
|
|
+ calls = []
|
|
|
+ results = inst.multicall(calls)
|
|
|
+ self.assertEqual(results, [])
|
|
|
+
|
|
|
+ def test_multicall_performs_noncallback_functions_serially(self):
|
|
|
+ class DummyNamespace(object):
|
|
|
+ def say(self, name):
|
|
|
+ """ @param string name Process name"""
|
|
|
+ return name
|
|
|
+ ns1 = DummyNamespace()
|
|
|
+ inst = self._makeOne([('ns1', ns1)])
|
|
|
+ calls = [
|
|
|
+ {'methodName': 'ns1.say', 'params': ['Alvin']},
|
|
|
+ {'methodName': 'ns1.say', 'params': ['Simon']},
|
|
|
+ {'methodName': 'ns1.say', 'params': ['Theodore']}
|
|
|
+ ]
|
|
|
+ results = inst.multicall(calls)
|
|
|
+ self.assertEqual(results, ['Alvin', 'Simon', 'Theodore'])
|
|
|
+
|
|
|
+ def test_multicall_catches_noncallback_exceptions(self):
|
|
|
+ import errno
|
|
|
+ from supervisor.xmlrpc import RPCError, Faults
|
|
|
+ class DummyNamespace(object):
|
|
|
+ def bad_name(self):
|
|
|
+ raise RPCError(Faults.BAD_NAME, 'foo')
|
|
|
+ def os_error(self):
|
|
|
+ raise OSError(errno.ENOENT)
|
|
|
+ ns1 = DummyNamespace()
|
|
|
+ inst = self._makeOne([('ns1', ns1)])
|
|
|
+ calls = [{'methodName': 'ns1.bad_name'}, {'methodName': 'ns1.os_error'}]
|
|
|
+ results = inst.multicall(calls)
|
|
|
+
|
|
|
+ bad_name = {'faultCode': Faults.BAD_NAME,
|
|
|
+ 'faultString': 'BAD_NAME: foo'}
|
|
|
+ os_error = {'faultCode': Faults.FAILED,
|
|
|
+ 'faultString': "FAILED: %s:2" % OSError}
|
|
|
+ self.assertEqual(results, [bad_name, os_error])
|
|
|
+
|
|
|
+ def test_multicall_catches_callback_exceptions(self):
|
|
|
+ import errno
|
|
|
+ from supervisor.xmlrpc import RPCError, Faults
|
|
|
from supervisor.http import NOT_DONE_YET
|
|
|
class DummyNamespace(object):
|
|
|
- def __init__(self):
|
|
|
- self.results = [NOT_DONE_YET, 1]
|
|
|
- def foo(self):
|
|
|
- """ @param string name The thing"""
|
|
|
+ def bad_name(self):
|
|
|
+ def inner():
|
|
|
+ raise RPCError(Faults.BAD_NAME, 'foo')
|
|
|
+ return inner
|
|
|
+ def os_error(self):
|
|
|
def inner():
|
|
|
- return self.results.pop(0)
|
|
|
+ raise OSError(errno.ENOENT)
|
|
|
return inner
|
|
|
ns1 = DummyNamespace()
|
|
|
inst = self._makeOne([('ns1', ns1)])
|
|
|
- multiproduce = inst.multicall([{'methodName':'ns1.foo'}])
|
|
|
- result = multiproduce()
|
|
|
- self.assertEqual(
|
|
|
- result,
|
|
|
- NOT_DONE_YET
|
|
|
- )
|
|
|
- result = multiproduce()
|
|
|
- self.assertEqual(
|
|
|
- result,
|
|
|
- [1]
|
|
|
- )
|
|
|
-
|
|
|
- def test_multicall_callback_returns_function_raises_RPCError(self):
|
|
|
- from supervisor.xmlrpc import Faults, RPCError
|
|
|
+ calls = [{'methodName': 'ns1.bad_name'}, {'methodName': 'ns1.os_error'}]
|
|
|
+ callback = inst.multicall(calls)
|
|
|
+ results = NOT_DONE_YET
|
|
|
+ while results is NOT_DONE_YET:
|
|
|
+ results = callback()
|
|
|
+
|
|
|
+ bad_name = {'faultCode': Faults.BAD_NAME,
|
|
|
+ 'faultString': 'BAD_NAME: foo'}
|
|
|
+ os_error = {'faultCode': Faults.FAILED,
|
|
|
+ 'faultString': "FAILED: %s:2" % OSError}
|
|
|
+ self.assertEqual(results, [bad_name, os_error])
|
|
|
+
|
|
|
+ def test_multicall_performs_callback_functions_serially(self):
|
|
|
+ from supervisor.http import NOT_DONE_YET
|
|
|
class DummyNamespace(object):
|
|
|
- def foo(self):
|
|
|
- """ @param string name The thing"""
|
|
|
+ def __init__(self):
|
|
|
+ self.stop_results = [NOT_DONE_YET, NOT_DONE_YET,
|
|
|
+ NOT_DONE_YET, 'stop result']
|
|
|
+ self.start_results = ['start result']
|
|
|
+ def stopProcess(self, name):
|
|
|
+ def inner():
|
|
|
+ result = self.stop_results.pop(0)
|
|
|
+ if result is not NOT_DONE_YET:
|
|
|
+ self.stopped = True
|
|
|
+ return result
|
|
|
+ return inner
|
|
|
+ def startProcess(self, name):
|
|
|
def inner():
|
|
|
- raise RPCError(Faults.UNKNOWN_METHOD)
|
|
|
+ if not self.stopped:
|
|
|
+ raise Exception("This should not raise")
|
|
|
+ return self.start_results.pop(0)
|
|
|
return inner
|
|
|
ns1 = DummyNamespace()
|
|
|
inst = self._makeOne([('ns1', ns1)])
|
|
|
- multiproduce = inst.multicall([{'methodName':'ns1.foo'}])
|
|
|
- result = multiproduce()
|
|
|
- self.assertEqual(
|
|
|
- result,
|
|
|
- [{'faultString': 'UNKNOWN_METHOD', 'faultCode': 1}],
|
|
|
- )
|
|
|
-
|
|
|
+ calls = [{'methodName': 'ns1.stopProcess',
|
|
|
+ 'params': {'name': 'foo'}},
|
|
|
+ {'methodName': 'ns1.startProcess',
|
|
|
+ 'params': {'name': 'foo'}}]
|
|
|
+ callback = inst.multicall(calls)
|
|
|
+ results = NOT_DONE_YET
|
|
|
+ while results is NOT_DONE_YET:
|
|
|
+ results = callback()
|
|
|
+ self.assertEqual(results, ['stop result', 'start result'])
|
|
|
|
|
|
class Test_gettags(unittest.TestCase):
|
|
|
def _callFUT(self, comment):
|