From 237c16f0fd3998f4a2e69d9096997d10af2cf8c9 Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Mon, 24 Nov 2008 12:51:03 -0700 Subject: Started moving xmlrpc-functions from ipalib.util to ipalib.rpc --- tests/test_ipalib/test_rpc.py | 123 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tests/test_ipalib/test_rpc.py (limited to 'tests/test_ipalib/test_rpc.py') diff --git a/tests/test_ipalib/test_rpc.py b/tests/test_ipalib/test_rpc.py new file mode 100644 index 00000000..14af2bf4 --- /dev/null +++ b/tests/test_ipalib/test_rpc.py @@ -0,0 +1,123 @@ +# Authors: +# Jason Gerard DeRose +# +# Copyright (C) 2008 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +Test the `ipalib.rpc` module. +""" + +from xmlrpclib import Binary, dumps, loads +import struct +from tests.util import raises +from ipalib import rpc + + +# A string that should have bytes 'x\00' through '\xff': +BINARY_BYTES = ''.join(struct.pack('B', d) for d in xrange(256)) +assert '\x00' in BINARY_BYTES and '\xff' in BINARY_BYTES +assert type(BINARY_BYTES) is str and len(BINARY_BYTES) == 256 + +# A UTF-8 encoded str +UTF8_BYTES = '\xd0\x9f\xd0\xb0\xd0\xb2\xd0\xb5\xd0\xbb' + +# The same UTF-8 data decoded (a unicode instance) +UNICODE_CHARS = u'\u041f\u0430\u0432\u0435\u043b' +assert UTF8_BYTES.decode('UTF-8') == UNICODE_CHARS +assert UNICODE_CHARS.encode('UTF-8') == UTF8_BYTES +assert UTF8_BYTES != UNICODE_CHARS + + +def dump_n_load(value): + (param, method) = loads( + dumps((value,)) + ) + return param[0] + + +def round_trip(value): + return rpc.xmlrpc_unwrap( + dump_n_load(rpc.xmlrpc_wrap(value)) + ) + + +def test_round_trip(): + """ + Test `ipalib.rpc.xmlrpc_wrap` and `ipalib.rpc.xmlrpc_unwrap`. + + This tests the two functions together with ``xmlrpclib.dumps()`` and + ``xmlrpclib.loads()`` in a full encode/dumps/loads/decode round trip. + """ + # We first test that our assumptions about xmlrpclib module in the Python + # standard library are correct: + assert dump_n_load(UTF8_BYTES) == UNICODE_CHARS + assert dump_n_load(UNICODE_CHARS) == UNICODE_CHARS + assert dump_n_load(Binary(BINARY_BYTES)).data == BINARY_BYTES + assert isinstance(dump_n_load(Binary(BINARY_BYTES)), Binary) + assert type(dump_n_load('hello')) is str + assert type(dump_n_load(u'hello')) is str + + # Now we test our wrap and unwrap methods in combination with dumps, loads: + # All str should come back str (because they get wrapped in + # xmlrpclib.Binary(). All unicode should come back unicode because str + # explicity get decoded by rpc.xmlrpc_unwrap() if they weren't already + # decoded by xmlrpclib.loads(). + assert round_trip(UTF8_BYTES) == UTF8_BYTES + assert round_trip(UNICODE_CHARS) == UNICODE_CHARS + assert round_trip(BINARY_BYTES) == BINARY_BYTES + assert type(round_trip('hello')) is str + assert type(round_trip(u'hello')) is unicode + assert round_trip('') == '' + assert round_trip(u'') == u'' + compound = [UTF8_BYTES, UNICODE_CHARS, BINARY_BYTES, + dict(utf8=UTF8_BYTES, chars=UNICODE_CHARS, data=BINARY_BYTES) + ] + assert round_trip(compound) == tuple(compound) + + +def test_xmlrpc_wrap(): + """ + Test the `ipalib.rpc.xmlrpc_wrap` function. + """ + f = rpc.xmlrpc_wrap + assert f([]) == tuple() + assert f({}) == dict() + b = f('hello') + assert isinstance(b, Binary) + assert b.data == 'hello' + u = f(u'hello') + assert type(u) is unicode + assert u == u'hello' + value = f([dict(one=False, two=u'hello'), None, 'hello']) + + +def test_xmlrpc_unwrap(): + """ + Test the `ipalib.rpc.xmlrpc_unwrap` function. + """ + f = rpc.xmlrpc_unwrap + assert f([]) == tuple() + assert f({}) == dict() + value = f(Binary(UTF8_BYTES)) + assert type(value) is str + assert value == UTF8_BYTES + assert f(UTF8_BYTES) == UNICODE_CHARS + assert f(UNICODE_CHARS) == UNICODE_CHARS + value = f([True, Binary('hello'), dict(one=1, two=UTF8_BYTES, three=None)]) + assert value == (True, 'hello', dict(one=1, two=UNICODE_CHARS, three=None)) + assert type(value[1]) is str + assert type(value[2]['two']) is unicode -- cgit From 2d458a12339fbb7ef006ff7defc1e2f541e2f23f Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Mon, 24 Nov 2008 21:34:01 -0700 Subject: Stared some RPC-related error cleanup; started work on ipa_server.rcp.xmlrpc plugin --- tests/test_ipalib/test_rpc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/test_ipalib/test_rpc.py') diff --git a/tests/test_ipalib/test_rpc.py b/tests/test_ipalib/test_rpc.py index 14af2bf4..e8d73931 100644 --- a/tests/test_ipalib/test_rpc.py +++ b/tests/test_ipalib/test_rpc.py @@ -32,10 +32,10 @@ BINARY_BYTES = ''.join(struct.pack('B', d) for d in xrange(256)) assert '\x00' in BINARY_BYTES and '\xff' in BINARY_BYTES assert type(BINARY_BYTES) is str and len(BINARY_BYTES) == 256 -# A UTF-8 encoded str +# A UTF-8 encoded str: UTF8_BYTES = '\xd0\x9f\xd0\xb0\xd0\xb2\xd0\xb5\xd0\xbb' -# The same UTF-8 data decoded (a unicode instance) +# The same UTF-8 data decoded (a unicode instance): UNICODE_CHARS = u'\u041f\u0430\u0432\u0435\u043b' assert UTF8_BYTES.decode('UTF-8') == UNICODE_CHARS assert UNICODE_CHARS.encode('UTF-8') == UTF8_BYTES @@ -60,7 +60,7 @@ def test_round_trip(): Test `ipalib.rpc.xmlrpc_wrap` and `ipalib.rpc.xmlrpc_unwrap`. This tests the two functions together with ``xmlrpclib.dumps()`` and - ``xmlrpclib.loads()`` in a full encode/dumps/loads/decode round trip. + ``xmlrpclib.loads()`` in a full wrap/dumps/loads/unwrap round trip. """ # We first test that our assumptions about xmlrpclib module in the Python # standard library are correct: -- cgit From 8a2902a2a240108e16561679e01f52b362097b3a Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Mon, 8 Dec 2008 12:34:38 -0700 Subject: Re-enable Python2.4 tests and fixed some small things broken under Python2.4 --- tests/test_ipalib/test_rpc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests/test_ipalib/test_rpc.py') diff --git a/tests/test_ipalib/test_rpc.py b/tests/test_ipalib/test_rpc.py index e8d73931..7af8c220 100644 --- a/tests/test_ipalib/test_rpc.py +++ b/tests/test_ipalib/test_rpc.py @@ -26,6 +26,7 @@ import struct from tests.util import raises from ipalib import rpc +# FIXME: These constants should be imported from tests.data # A string that should have bytes 'x\00' through '\xff': BINARY_BYTES = ''.join(struct.pack('B', d) for d in xrange(256)) @@ -39,7 +40,7 @@ UTF8_BYTES = '\xd0\x9f\xd0\xb0\xd0\xb2\xd0\xb5\xd0\xbb' UNICODE_CHARS = u'\u041f\u0430\u0432\u0435\u043b' assert UTF8_BYTES.decode('UTF-8') == UNICODE_CHARS assert UNICODE_CHARS.encode('UTF-8') == UTF8_BYTES -assert UTF8_BYTES != UNICODE_CHARS + def dump_n_load(value): -- cgit From f4f010ae8d2628b09b88b3a995f4b3b008b0608c Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Mon, 8 Dec 2008 15:10:01 -0700 Subject: tests.test_ipalib.test_rpc now imports constants from tests.data --- tests/test_ipalib/test_rpc.py | 48 +++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) (limited to 'tests/test_ipalib/test_rpc.py') diff --git a/tests/test_ipalib/test_rpc.py b/tests/test_ipalib/test_rpc.py index 7af8c220..614db607 100644 --- a/tests/test_ipalib/test_rpc.py +++ b/tests/test_ipalib/test_rpc.py @@ -22,26 +22,10 @@ Test the `ipalib.rpc` module. """ from xmlrpclib import Binary, dumps, loads -import struct from tests.util import raises +from tests.data import binary_bytes, utf8_bytes, unicode_str from ipalib import rpc -# FIXME: These constants should be imported from tests.data - -# A string that should have bytes 'x\00' through '\xff': -BINARY_BYTES = ''.join(struct.pack('B', d) for d in xrange(256)) -assert '\x00' in BINARY_BYTES and '\xff' in BINARY_BYTES -assert type(BINARY_BYTES) is str and len(BINARY_BYTES) == 256 - -# A UTF-8 encoded str: -UTF8_BYTES = '\xd0\x9f\xd0\xb0\xd0\xb2\xd0\xb5\xd0\xbb' - -# The same UTF-8 data decoded (a unicode instance): -UNICODE_CHARS = u'\u041f\u0430\u0432\u0435\u043b' -assert UTF8_BYTES.decode('UTF-8') == UNICODE_CHARS -assert UNICODE_CHARS.encode('UTF-8') == UTF8_BYTES - - def dump_n_load(value): (param, method) = loads( @@ -65,10 +49,10 @@ def test_round_trip(): """ # We first test that our assumptions about xmlrpclib module in the Python # standard library are correct: - assert dump_n_load(UTF8_BYTES) == UNICODE_CHARS - assert dump_n_load(UNICODE_CHARS) == UNICODE_CHARS - assert dump_n_load(Binary(BINARY_BYTES)).data == BINARY_BYTES - assert isinstance(dump_n_load(Binary(BINARY_BYTES)), Binary) + assert dump_n_load(utf8_bytes) == unicode_str + assert dump_n_load(unicode_str) == unicode_str + assert dump_n_load(Binary(binary_bytes)).data == binary_bytes + assert isinstance(dump_n_load(Binary(binary_bytes)), Binary) assert type(dump_n_load('hello')) is str assert type(dump_n_load(u'hello')) is str @@ -77,15 +61,15 @@ def test_round_trip(): # xmlrpclib.Binary(). All unicode should come back unicode because str # explicity get decoded by rpc.xmlrpc_unwrap() if they weren't already # decoded by xmlrpclib.loads(). - assert round_trip(UTF8_BYTES) == UTF8_BYTES - assert round_trip(UNICODE_CHARS) == UNICODE_CHARS - assert round_trip(BINARY_BYTES) == BINARY_BYTES + assert round_trip(utf8_bytes) == utf8_bytes + assert round_trip(unicode_str) == unicode_str + assert round_trip(binary_bytes) == binary_bytes assert type(round_trip('hello')) is str assert type(round_trip(u'hello')) is unicode assert round_trip('') == '' assert round_trip(u'') == u'' - compound = [UTF8_BYTES, UNICODE_CHARS, BINARY_BYTES, - dict(utf8=UTF8_BYTES, chars=UNICODE_CHARS, data=BINARY_BYTES) + compound = [utf8_bytes, unicode_str, binary_bytes, + dict(utf8=utf8_bytes, chars=unicode_str, data=binary_bytes) ] assert round_trip(compound) == tuple(compound) @@ -113,12 +97,12 @@ def test_xmlrpc_unwrap(): f = rpc.xmlrpc_unwrap assert f([]) == tuple() assert f({}) == dict() - value = f(Binary(UTF8_BYTES)) + value = f(Binary(utf8_bytes)) assert type(value) is str - assert value == UTF8_BYTES - assert f(UTF8_BYTES) == UNICODE_CHARS - assert f(UNICODE_CHARS) == UNICODE_CHARS - value = f([True, Binary('hello'), dict(one=1, two=UTF8_BYTES, three=None)]) - assert value == (True, 'hello', dict(one=1, two=UNICODE_CHARS, three=None)) + assert value == utf8_bytes + assert f(utf8_bytes) == unicode_str + assert f(unicode_str) == unicode_str + value = f([True, Binary('hello'), dict(one=1, two=utf8_bytes, three=None)]) + assert value == (True, 'hello', dict(one=1, two=unicode_str, three=None)) assert type(value[1]) is str assert type(value[2]['two']) is unicode -- cgit From 6be5e4a0a55c1ba048444430afc0e01b3048d8b9 Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Thu, 15 Jan 2009 23:52:50 -0700 Subject: ipalib.rpc: now using allow_none=True after conversation with Rob; added xml_dumps() and xml_loads() functions; some name cleanup --- tests/test_ipalib/test_rpc.py | 108 +++++++++++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 22 deletions(-) (limited to 'tests/test_ipalib/test_rpc.py') diff --git a/tests/test_ipalib/test_rpc.py b/tests/test_ipalib/test_rpc.py index 614db607..eba35261 100644 --- a/tests/test_ipalib/test_rpc.py +++ b/tests/test_ipalib/test_rpc.py @@ -21,64 +21,68 @@ Test the `ipalib.rpc` module. """ -from xmlrpclib import Binary, dumps, loads -from tests.util import raises +from xmlrpclib import Binary, Fault, dumps, loads +from tests.util import raises, assert_equal from tests.data import binary_bytes, utf8_bytes, unicode_str from ipalib import rpc def dump_n_load(value): (param, method) = loads( - dumps((value,)) + dumps((value,), allow_none=True) ) return param[0] def round_trip(value): - return rpc.xmlrpc_unwrap( - dump_n_load(rpc.xmlrpc_wrap(value)) + return rpc.xml_unwrap( + dump_n_load(rpc.xml_wrap(value)) ) def test_round_trip(): """ - Test `ipalib.rpc.xmlrpc_wrap` and `ipalib.rpc.xmlrpc_unwrap`. + Test `ipalib.rpc.xml_wrap` and `ipalib.rpc.xml_unwrap`. This tests the two functions together with ``xmlrpclib.dumps()`` and ``xmlrpclib.loads()`` in a full wrap/dumps/loads/unwrap round trip. """ # We first test that our assumptions about xmlrpclib module in the Python # standard library are correct: - assert dump_n_load(utf8_bytes) == unicode_str - assert dump_n_load(unicode_str) == unicode_str - assert dump_n_load(Binary(binary_bytes)).data == binary_bytes + assert_equal(dump_n_load(utf8_bytes), unicode_str) + assert_equal(dump_n_load(unicode_str), unicode_str) + assert_equal(dump_n_load(Binary(binary_bytes)).data, binary_bytes) assert isinstance(dump_n_load(Binary(binary_bytes)), Binary) assert type(dump_n_load('hello')) is str assert type(dump_n_load(u'hello')) is str + assert_equal(dump_n_load(''), '') + assert_equal(dump_n_load(u''), '') + assert dump_n_load(None) is None # Now we test our wrap and unwrap methods in combination with dumps, loads: # All str should come back str (because they get wrapped in # xmlrpclib.Binary(). All unicode should come back unicode because str - # explicity get decoded by rpc.xmlrpc_unwrap() if they weren't already + # explicity get decoded by rpc.xml_unwrap() if they weren't already # decoded by xmlrpclib.loads(). - assert round_trip(utf8_bytes) == utf8_bytes - assert round_trip(unicode_str) == unicode_str - assert round_trip(binary_bytes) == binary_bytes + assert_equal(round_trip(utf8_bytes), utf8_bytes) + assert_equal(round_trip(unicode_str), unicode_str) + assert_equal(round_trip(binary_bytes), binary_bytes) assert type(round_trip('hello')) is str assert type(round_trip(u'hello')) is unicode - assert round_trip('') == '' - assert round_trip(u'') == u'' - compound = [utf8_bytes, unicode_str, binary_bytes, + assert_equal(round_trip(''), '') + assert_equal(round_trip(u''), u'') + assert round_trip(None) is None + compound = [utf8_bytes, None, binary_bytes, (None, unicode_str), dict(utf8=utf8_bytes, chars=unicode_str, data=binary_bytes) ] assert round_trip(compound) == tuple(compound) -def test_xmlrpc_wrap(): +def test_xml_wrap(): """ - Test the `ipalib.rpc.xmlrpc_wrap` function. + Test the `ipalib.rpc.xml_wrap` function. """ - f = rpc.xmlrpc_wrap + f = rpc.xml_wrap assert f([]) == tuple() assert f({}) == dict() b = f('hello') @@ -90,11 +94,11 @@ def test_xmlrpc_wrap(): value = f([dict(one=False, two=u'hello'), None, 'hello']) -def test_xmlrpc_unwrap(): +def test_xml_unwrap(): """ - Test the `ipalib.rpc.xmlrpc_unwrap` function. + Test the `ipalib.rpc.xml_unwrap` function. """ - f = rpc.xmlrpc_unwrap + f = rpc.xml_unwrap assert f([]) == tuple() assert f({}) == dict() value = f(Binary(utf8_bytes)) @@ -106,3 +110,63 @@ def test_xmlrpc_unwrap(): assert value == (True, 'hello', dict(one=1, two=unicode_str, three=None)) assert type(value[1]) is str assert type(value[2]['two']) is unicode + + +def test_xml_dumps(): + """ + Test the `ipalib.rpc.xml_dumps` function. + """ + f = rpc.xml_dumps + params = (binary_bytes, utf8_bytes, unicode_str, None) + + # Test serializing an RPC request: + data = f(params, 'the_method') + (p, m) = loads(data) + assert_equal(m, u'the_method') + assert type(p) is tuple + assert rpc.xml_unwrap(p) == params + + # Test serializing an RPC response: + data = f((params,), methodresponse=True) + (tup, m) = loads(data) + assert m is None + assert len(tup) == 1 + assert type(tup) is tuple + assert rpc.xml_unwrap(tup[0]) == params + + # Test serializing an RPC response containing a Fault: + fault = Fault(69, unicode_str) + data = f(fault, methodresponse=True) + e = raises(Fault, loads, data) + assert e.faultCode == 69 + assert_equal(e.faultString, unicode_str) + + +def test_xml_loads(): + """ + Test the `ipalib.rpc.xml_loads` function. + """ + f = rpc.xml_loads + params = (binary_bytes, utf8_bytes, unicode_str, None) + wrapped = rpc.xml_wrap(params) + + # Test un-serializing an RPC request: + data = dumps(wrapped, 'the_method', allow_none=True) + (p, m) = f(data) + assert_equal(m, u'the_method') + assert_equal(p, params) + + # Test un-serializing an RPC response: + data = dumps((wrapped,), methodresponse=True, allow_none=True) + (tup, m) = f(data) + assert m is None + assert len(tup) == 1 + assert type(tup) is tuple + assert_equal(tup[0], params) + + # Test un-serializing an RPC response containing a Fault: + fault = Fault(69, unicode_str) + data = dumps(fault, methodresponse=True, allow_none=True) + e = raises(Fault, f, data) + assert e.faultCode == 69 + assert_equal(e.faultString, unicode_str) -- cgit From 55fba5420d8ea57931937728102094492ca73d86 Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Mon, 19 Jan 2009 21:10:42 -0700 Subject: Added rpc.xmlclient backend plugin for forwarding; added corresponding unit tests --- tests/test_ipalib/test_rpc.py | 81 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 2 deletions(-) (limited to 'tests/test_ipalib/test_rpc.py') diff --git a/tests/test_ipalib/test_rpc.py b/tests/test_ipalib/test_rpc.py index eba35261..296e9bc1 100644 --- a/tests/test_ipalib/test_rpc.py +++ b/tests/test_ipalib/test_rpc.py @@ -21,10 +21,16 @@ Test the `ipalib.rpc` module. """ +import threading from xmlrpclib import Binary, Fault, dumps, loads -from tests.util import raises, assert_equal +from tests.util import raises, assert_equal, PluginTester, DummyClass from tests.data import binary_bytes, utf8_bytes, unicode_str -from ipalib import rpc +from ipalib.frontend import Command +from ipalib.request import context +from ipalib import rpc, errors2 + + +std_compound = (binary_bytes, utf8_bytes, unicode_str) def dump_n_load(value): @@ -170,3 +176,74 @@ def test_xml_loads(): e = raises(Fault, f, data) assert e.faultCode == 69 assert_equal(e.faultString, unicode_str) + + +class test_xmlclient(PluginTester): + """ + Test the `ipalib.rpc.xmlclient` plugin. + """ + _plugin = rpc.xmlclient + + def test_forward(self): + """ + Test the `ipalib.rpc.xmlclient.forward` method. + """ + class user_add(Command): + pass + + # Test that ValueError is raised when forwarding a command that is not + # in api.Command: + (o, api, home) = self.instance('Backend', in_server=False) + e = raises(ValueError, o.forward, 'user_add') + assert str(e) == '%s.forward(): %r not in api.Command' % ( + 'xmlclient', 'user_add' + ) + + # Test that StandardError is raised when context.xmlconn does not exist: + (o, api, home) = self.instance('Backend', user_add, in_server=False) + e = raises(StandardError, o.forward, 'user_add') + assert str(e) == '%s.forward(%r): need context.xmlconn in thread %r' % ( + 'xmlclient', 'user_add', threading.currentThread().getName() + ) + + args = (binary_bytes, utf8_bytes, unicode_str) + kw = dict(one=binary_bytes, two=utf8_bytes, three=unicode_str) + params = args + (kw,) + result = (unicode_str, binary_bytes, utf8_bytes) + context.xmlconn = DummyClass( + ( + 'user_add', + (rpc.xml_wrap(params),), + {}, + rpc.xml_wrap(result), + ), + ( + 'user_add', + (rpc.xml_wrap(params),), + {}, + Fault(3005, u"'four' is required"), # RequirementError + ), + ( + 'user_add', + (rpc.xml_wrap(params),), + {}, + Fault(700, u'no such error'), # There is no error 700 + ), + + ) + + # Test with a successful return value: + assert o.forward('user_add', *args, **kw) == result + + # Test with an errno the client knows: + e = raises(errors2.RequirementError, o.forward, 'user_add', *args, **kw) + assert_equal(e.message, u"'four' is required") + + # Test with an errno the client doesn't know + e = raises(errors2.UnknownError, o.forward, 'user_add', *args, **kw) + assert_equal(e.code, 700) + assert_equal(e.error, u'no such error') + + assert context.xmlconn._calledall() is True + + del context.xmlconn -- cgit