class SystemAPITest(TestCase): def setUp(self): super(SystemAPITest, self).setUp() self.mapper = Mapper() self.dispatcher = Dispatcher(self.mapper) self.context = CallContext(user=None, mapper=self.mapper, dispatcher=self.dispatcher) self.system_api = SystemAPI(self.context) def test_listMethods_just_calls_mapper_list_methods(self): obj = object() self.mapper.list_methods = lambda: obj retval = self.system_api.listMethods() self.assertEqual(retval, obj) def test_methodHelp_returns_blank_when_method_has_no_docstring(self): class TestAPI(ExposedAPI): def method(self): pass self.mapper.register(TestAPI) retval = self.system_api.methodHelp("TestAPI.method") self.assertEqual(retval, "") def test_methodHelp_returns_the_docstring(self): class TestAPI(ExposedAPI): def method(self): """docstring""" self.mapper.register(TestAPI) retval = self.system_api.methodHelp("TestAPI.method") self.assertEqual(retval, "docstring") def test_methodHelp_strips_the_leading_whitespce(self): class TestAPI(ExposedAPI): def method(self): """ line 1 line 2 """ self.mapper.register(TestAPI) retval = self.system_api.methodHelp("TestAPI.method") self.assertEqual(retval, "line 1\nline 2") def test_methodSignature_returns_undef_by_default(self): class TestAPI(ExposedAPI): def method(self): pass self.mapper.register(TestAPI) retval = self.system_api.methodSignature("TestAPI.method") self.assertEqual(retval, 'undef') def test_methodSignature_returns_signature_when_defined(self): class TestAPI(ExposedAPI): @xml_rpc_signature('str', 'int') def int_to_str(value): return "%s" % value self.mapper.register(TestAPI) retval = self.system_api.methodSignature("TestAPI.int_to_str") self.assertEqual(retval, ['str', 'int']) def test_multicall_with_empty_list(self): retval = self.system_api.multicall([]) self.assertEqual(retval, []) def test_multicall_boxes_normal_return_values_in_lists(self): # The return value of multicall is more complex than one might # originally think: each return value is boxed in a one-element list # to be different from unboxed faults. class TestAPI(ExposedAPI): def foo(self): return 1 self.mapper.register(TestAPI) calls = [ { "methodName": "TestAPI.foo", "params": [] }, ] observed = self.system_api.multicall(calls) self.assertIsInstance(observed[0], list) self.assertEqual(observed, [[1]]) def test_multicall_calls_methods(self): class TestAPI(ExposedAPI): def foo(self): return "foo-result" def bar(self, arg): return arg self.mapper.register(TestAPI) calls = [ { "methodName": "TestAPI.foo", "params": [] }, { "methodName": "TestAPI.bar", "params": ["bar-result"] }, ] expected = [["foo-result"], ["bar-result"]] observerd = self.system_api.multicall(calls) self.assertEqual(observerd, expected) def test_multicall_does_not_box_faults(self): # See comment in test_multicall_boxes_normal_return_values_in_lists # above. Each fault is returned directly and is not boxed in a list. class TestAPI(ExposedAPI): def boom(self): raise xmlrpclib.Fault(1, "boom") self.mapper.register(TestAPI) calls = [ { "methodName": "TestAPI.boom", "params": [] }, ] observed = self.system_api.multicall(calls) self.assertIsInstance(observed[0], xmlrpclib.Fault) def test_multicall_just_returns_faults(self): # If one method being called returns a fault, any subsequent method # calls are still performed. class TestAPI(ExposedAPI): def boom(self): raise xmlrpclib.Fault(1, "boom") def echo(self, arg): return arg self.mapper.register(TestAPI) calls = [ { "methodName": "TestAPI.echo", "params": ["before"] }, { "methodName": "TestAPI.boom", "params": [] }, { "methodName": "TestAPI.echo", "params": ["after"] }, ] observed = self.system_api.multicall(calls) # echo is called with 'before' self.assertEqual(observed[0], ["before"]) # Note that at this point the exception is returned as-is. It will be # converted to proper xml-rpc encoding by the dispatcher. Here we do # manual comparison as xmlrpclib.Fault does not implement __eq__ # properly. self.assertEqual(observed[1].faultCode, 1) self.assertEqual(observed[1].faultString, "boom") # echo is called with 'after' self.assertEqual(observed[2], ["after"]) def test_multicall_wants_a_list_of_sub_calls(self): # XXX: Use TestCaseWithInvariants in the future for bad_stuff in [None, {}, True, False, -1, 10000, "foobar"]: try: self.system_api.multicall(bad_stuff) except xmlrpclib.Fault as ex: self.assertEqual( ex.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) self.assertEqual( ex.faultString, "system.multicall expected a list of methods to call") else: self.fail("Should have raised an exception") def test_multicall_subcall_wants_a_dict(self): # XXX: Use TestCaseWithInvariants in the future for bad_stuff in [None, [], True, False, -1, 10000, "foobar"]: [result] = self.system_api.multicall([bad_stuff]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual(result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_wants_methodName(self): [result] = self.system_api.multicall([{}]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual(result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_wants_methodName_to_be_a_string(self): [result] = self.system_api.multicall([{"methodName": False}]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual(result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_wants_params(self): [result] = self.system_api.multicall([{ "methodName": "system.listMethods" }]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual(result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_wants_params_to_be_a_list(self): [result] = self.system_api.multicall([{ "methodName": "system.listMethods", "params": False }]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual(result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_rejects_other_arguments(self): [result] = self.system_api.multicall([{ "methodName": "system.listMethods", "params": [], "other": 1 }]) self.assertIsInstance(result, xmlrpclib.Fault) print(result.faultString) self.assertEqual(result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_listMethods_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.listMethods", self.system_api.listMethods()) def test_methodHelp_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.methodHelp", self.system_api.listMethods()) def test_methodSignature_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.methodSignature", self.system_api.listMethods()) def test_getCapabilities_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.getCapabilities", self.system_api.listMethods()) def test_multicall_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.multicall", self.system_api.listMethods()) def test_fault_interop_capabilitiy_supported(self): self.assertIn("faults_interop", self.system_api.getCapabilities()) def test_auth_token_capability_supported(self): self.assertIn("auth_token", self.system_api.getCapabilities()) def test_introspect_capability_supported(self): self.assertIn("introspect", self.system_api.getCapabilities())
class SystemAPITest(TestCase): def setUp(self): super(SystemAPITest, self).setUp() self.mapper = Mapper() self.dispatcher = Dispatcher(self.mapper) self.context = CallContext( user=None, mapper=self.mapper, dispatcher=self.dispatcher) self.system_api = SystemAPI(self.context) def test_listMethods_just_calls_mapper_list_methods(self): obj = object() self.mapper.list_methods = lambda: obj retval = self.system_api.listMethods() self.assertEqual(retval, obj) def test_methodHelp_returns_blank_when_method_has_no_docstring(self): class TestAPI(ExposedAPI): def method(self): pass self.mapper.register(TestAPI, "TestAPI") retval = self.system_api.methodHelp("TestAPI.method") self.assertEqual(retval, "") def test_methodHelp_returns_the_docstring(self): class TestAPI(ExposedAPI): def method(self): """docstring""" self.mapper.register(TestAPI, "TestAPI") retval = self.system_api.methodHelp("TestAPI.method") self.assertEqual(retval, "docstring") def test_methodHelp_strips_the_leading_whitespce(self): class TestAPI(ExposedAPI): def method(self): """ line 1 line 2 """ self.mapper.register(TestAPI, "TestAPI") retval = self.system_api.methodHelp("TestAPI.method") self.assertEqual(retval, "line 1\nline 2") def test_methodSignature_returns_undef_by_default(self): class TestAPI(ExposedAPI): def method(self): pass self.mapper.register(TestAPI, "TestAPI") retval = self.system_api.methodSignature("TestAPI.method") self.assertEqual(retval, 'undef') def test_methodSignature_returns_signature_when_defined(self): class TestAPI(ExposedAPI): @xml_rpc_signature('str', 'int') def int_to_str(value): return "%s" % value self.mapper.register(TestAPI, "TestAPI") retval = self.system_api.methodSignature("TestAPI.int_to_str") self.assertEqual(retval, ['str', 'int']) def test_multicall_with_empty_list(self): retval = self.system_api.multicall([]) self.assertEqual(retval, []) def test_multicall_boxes_normal_return_values_in_lists(self): # The return value of multicall is more complex than one might # originally think: each return value is boxed in a one-element list # to be different from unboxed faults. class TestAPI(ExposedAPI): def foo(self): return 1 self.mapper.register(TestAPI, "TestAPI") calls = [ {"methodName": "TestAPI.foo", "params": []}, ] observed = self.system_api.multicall(calls) self.assertIsInstance(observed[0], list) self.assertEqual(observed, [[1]]) def test_multicall_calls_methods(self): class TestAPI(ExposedAPI): def foo(self): return "foo-result" def bar(self, arg): return arg self.mapper.register(TestAPI, "TestAPI") calls = [ {"methodName": "TestAPI.foo", "params": []}, {"methodName": "TestAPI.bar", "params": ["bar-result"]}, ] expected = [ ["foo-result"], ["bar-result"] ] observerd = self.system_api.multicall(calls) self.assertEqual(observerd, expected) def test_multicall_does_not_box_faults(self): # See comment in test_multicall_boxes_normal_return_values_in_lists # above. Each fault is returned directly and is not boxed in a list. class TestAPI(ExposedAPI): def boom(self): raise xmlrpclib.Fault(1, "boom") self.mapper.register(TestAPI, "TestAPI") calls = [ {"methodName": "TestAPI.boom", "params": []}, ] observed = self.system_api.multicall(calls) self.assertIsInstance(observed[0], xmlrpclib.Fault) def test_multicall_just_returns_faults(self): # If one method being called returns a fault, any subsequent method # calls are still performed. class TestAPI(ExposedAPI): def boom(self): raise xmlrpclib.Fault(1, "boom") def echo(self, arg): return arg self.mapper.register(TestAPI, "TestAPI") calls = [ {"methodName": "TestAPI.echo", "params": ["before"]}, {"methodName": "TestAPI.boom", "params": []}, {"methodName": "TestAPI.echo", "params": ["after"]}, ] observed = self.system_api.multicall(calls) # echo is called with 'before' self.assertEqual(observed[0], ["before"]) # Note that at this point the exception is returned as-is. It will be # converted to proper xml-rpc encoding by the dispatcher. Here we do # manual comparison as xmlrpclib.Fault does not implement __eq__ # properly. self.assertEqual(observed[1].faultCode, 1) self.assertEqual(observed[1].faultString, "boom") # echo is called with 'after' self.assertEqual(observed[2], ["after"]) def test_multicall_wants_a_list_of_sub_calls(self): # XXX: Use TestCaseWithInvariants in the future for bad_stuff in [None, {}, True, False, -1, 10000, "foobar"]: try: self.system_api.multicall(bad_stuff) except xmlrpclib.Fault as ex: self.assertEqual(ex.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) self.assertEqual(ex.faultString, "system.multicall expected a list of methods to call") else: self.fail("Should have raised an exception") def test_multicall_subcall_wants_a_dict(self): # XXX: Use TestCaseWithInvariants in the future for bad_stuff in [None, [], True, False, -1, 10000, "foobar"]: [result] = self.system_api.multicall([bad_stuff]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual( result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_wants_methodName(self): [result] = self.system_api.multicall([{}]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual( result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_wants_methodName_to_be_a_string(self): [result] = self.system_api.multicall( [{"methodName": False}]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual( result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_wants_params(self): [result] = self.system_api.multicall( [{"methodName": "system.listMethods"}]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual( result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_wants_params_to_be_a_list(self): [result] = self.system_api.multicall( [{"methodName": "system.listMethods", "params": False}]) self.assertIsInstance(result, xmlrpclib.Fault) self.assertEqual( result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_multicall_subcall_rejects_other_arguments(self): [result] = self.system_api.multicall( [{"methodName": "system.listMethods", "params": [], "other": 1}]) self.assertIsInstance(result, xmlrpclib.Fault) print(result.faultString) self.assertEqual( result.faultCode, FaultCodes.ServerError.INVALID_METHOD_PARAMETERS) def test_listMethods_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.listMethods", self.system_api.listMethods()) def test_methodHelp_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.methodHelp", self.system_api.listMethods()) def test_methodSignature_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.methodSignature", self.system_api.listMethods()) def test_getCapabilities_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.getCapabilities", self.system_api.listMethods()) def test_multicall_exists(self): self.mapper.register(SystemAPI, 'system') self.assertIn("system.multicall", self.system_api.listMethods()) def test_fault_interop_capabilitiy_supported(self): self.assertIn("faults_interop", self.system_api.getCapabilities()) def test_auth_token_capability_supported(self): self.assertIn("auth_token", self.system_api.getCapabilities()) def test_introspect_capability_supported(self): self.assertIn("introspect", self.system_api.getCapabilities())