diff options
author | Jim Rollenhagen <jim@jimrollenhagen.com> | 2019-09-26 09:43:27 -0400 |
---|---|---|
committer | Jim Rollenhagen <jim@jimrollenhagen.com> | 2019-09-26 09:43:27 -0400 |
commit | e9c6edfe510f4ed407f8d2d84b4b931a382b48b3 (patch) | |
tree | 94bbd6a34bcf09e99f7ae1be88b19960192d6adb /wsme/tests | |
parent | 1d73d6e50411ebc45fb96a6ed3c63ca91a500323 (diff) | |
download | wsme-master.tar.gz |
Diffstat (limited to 'wsme/tests')
-rw-r--r-- | wsme/tests/__init__.py | 0 | ||||
-rw-r--r-- | wsme/tests/protocol.py | 720 | ||||
-rw-r--r-- | wsme/tests/test_api.py | 419 | ||||
-rw-r--r-- | wsme/tests/test_exc.py | 40 | ||||
-rw-r--r-- | wsme/tests/test_protocols.py | 70 | ||||
-rw-r--r-- | wsme/tests/test_protocols_commons.py | 159 | ||||
-rw-r--r-- | wsme/tests/test_restjson.py | 779 | ||||
-rw-r--r-- | wsme/tests/test_restxml.py | 211 | ||||
-rw-r--r-- | wsme/tests/test_root.py | 122 | ||||
-rw-r--r-- | wsme/tests/test_spore.py | 51 | ||||
-rw-r--r-- | wsme/tests/test_types.py | 667 | ||||
-rw-r--r-- | wsme/tests/test_utils.py | 97 |
12 files changed, 0 insertions, 3335 deletions
diff --git a/wsme/tests/__init__.py b/wsme/tests/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/wsme/tests/__init__.py +++ /dev/null diff --git a/wsme/tests/protocol.py b/wsme/tests/protocol.py deleted file mode 100644 index 1c41f8c..0000000 --- a/wsme/tests/protocol.py +++ /dev/null @@ -1,720 +0,0 @@ -# coding=utf-8 - -import unittest -import warnings -import datetime -import decimal -import six - -from six import u, b - -from webtest import TestApp - -from wsme import WSRoot, Unset -from wsme import expose, validate -import wsme.types -import wsme.utils - -warnings.filterwarnings('ignore', module='webob.dec') - -binarysample = b('\x00\xff\x43') - -try: - 1 / 0 -except ZeroDivisionError as e: - zerodivisionerrormsg = str(e) - - -class CallException(RuntimeError): - def __init__(self, faultcode, faultstring, debuginfo): - self.faultcode = faultcode - self.faultstring = faultstring - self.debuginfo = debuginfo - - def __str__(self): - return 'faultcode=%s, faultstring=%s, debuginfo=%s' % ( - self.faultcode, self.faultstring, self.debuginfo - ) - - -myenumtype = wsme.types.Enum(wsme.types.bytes, 'v1', 'v2') - - -class NestedInner(object): - aint = int - - def __init__(self, aint=None): - self.aint = aint - - -class NestedOuter(object): - inner = NestedInner - inner_array = wsme.types.wsattr([NestedInner]) - inner_dict = {wsme.types.text: NestedInner} - - def __init__(self): - self.inner = NestedInner(0) - - -class NamedAttrsObject(object): - def __init__(self, v1=Unset, v2=Unset): - self.attr_1 = v1 - self.attr_2 = v2 - - attr_1 = wsme.types.wsattr(int, name='attr.1') - attr_2 = wsme.types.wsattr(int, name='attr.2') - - -class CustomObject(object): - aint = int - name = wsme.types.text - - -class ExtendedInt(wsme.types.UserType): - basetype = int - name = "Extended integer" - - -class NestedInnerApi(object): - @expose(bool) - def deepfunction(self): - return True - - -class NestedOuterApi(object): - inner = NestedInnerApi() - - -class ReturnTypes(object): - @expose(wsme.types.bytes) - def getbytes(self): - return b("astring") - - @expose(wsme.types.text) - def gettext(self): - return u('\xe3\x81\xae') - - @expose(int) - def getint(self): - return 2 - - @expose(float) - def getfloat(self): - return 3.14159265 - - @expose(decimal.Decimal) - def getdecimal(self): - return decimal.Decimal('3.14159265') - - @expose(datetime.date) - def getdate(self): - return datetime.date(1994, 1, 26) - - @expose(bool) - def getbooltrue(self): - return True - - @expose(bool) - def getboolfalse(self): - return False - - @expose(datetime.time) - def gettime(self): - return datetime.time(12, 0, 0) - - @expose(datetime.datetime) - def getdatetime(self): - return datetime.datetime(1994, 1, 26, 12, 0, 0) - - @expose(wsme.types.binary) - def getbinary(self): - return binarysample - - @expose(NestedOuter) - def getnested(self): - n = NestedOuter() - return n - - @expose([wsme.types.bytes]) - def getbytesarray(self): - return [b("A"), b("B"), b("C")] - - @expose([NestedOuter]) - def getnestedarray(self): - return [NestedOuter(), NestedOuter()] - - @expose({wsme.types.bytes: NestedOuter}) - def getnesteddict(self): - return {b('a'): NestedOuter(), b('b'): NestedOuter()} - - @expose(NestedOuter) - def getobjectarrayattribute(self): - obj = NestedOuter() - obj.inner_array = [NestedInner(12), NestedInner(13)] - return obj - - @expose(NestedOuter) - def getobjectdictattribute(self): - obj = NestedOuter() - obj.inner_dict = { - '12': NestedInner(12), - '13': NestedInner(13) - } - return obj - - @expose(myenumtype) - def getenum(self): - return b('v2') - - @expose(NamedAttrsObject) - def getnamedattrsobj(self): - return NamedAttrsObject(5, 6) - - -class ArgTypes(object): - def assertEqual(self, a, b): - if not (a == b): - raise AssertionError('%s != %s' % (a, b)) - - def assertIsInstance(self, value, v_type): - assert isinstance(value, v_type), ("%s is not instance of type %s" % - (value, v_type)) - - @expose(wsme.types.bytes) - @validate(wsme.types.bytes) - def setbytes(self, value): - print(repr(value)) - self.assertEqual(type(value), wsme.types.bytes) - return value - - @expose(wsme.types.text) - @validate(wsme.types.text) - def settext(self, value): - print(repr(value)) - self.assertEqual(type(value), wsme.types.text) - return value - - @expose(wsme.types.text) - @validate(wsme.types.text) - def settextnone(self, value): - print(repr(value)) - self.assertEqual(type(value), type(None)) - return value - - @expose(bool) - @validate(bool) - def setbool(self, value): - print(repr(value)) - self.assertEqual(type(value), bool) - return value - - @expose(int) - @validate(int) - def setint(self, value): - print(repr(value)) - self.assertEqual(type(value), int) - return value - - @expose(float) - @validate(float) - def setfloat(self, value): - print(repr(value)) - self.assertEqual(type(value), float) - return value - - @expose(decimal.Decimal) - @validate(decimal.Decimal) - def setdecimal(self, value): - print(repr(value)) - self.assertEqual(type(value), decimal.Decimal) - return value - - @expose(datetime.date) - @validate(datetime.date) - def setdate(self, value): - print(repr(value)) - self.assertEqual(type(value), datetime.date) - return value - - @expose(datetime.time) - @validate(datetime.time) - def settime(self, value): - print(repr(value)) - self.assertEqual(type(value), datetime.time) - return value - - @expose(datetime.datetime) - @validate(datetime.datetime) - def setdatetime(self, value): - print(repr(value)) - self.assertEqual(type(value), datetime.datetime) - return value - - @expose(wsme.types.binary) - @validate(wsme.types.binary) - def setbinary(self, value): - print(repr(value)) - self.assertEqual(type(value), six.binary_type) - return value - - @expose([wsme.types.bytes]) - @validate([wsme.types.bytes]) - def setbytesarray(self, value): - print(repr(value)) - self.assertEqual(type(value), list) - self.assertEqual(type(value[0]), wsme.types.bytes) - return value - - @expose([wsme.types.text]) - @validate([wsme.types.text]) - def settextarray(self, value): - print(repr(value)) - self.assertEqual(type(value), list) - self.assertEqual(type(value[0]), wsme.types.text) - return value - - @expose([datetime.datetime]) - @validate([datetime.datetime]) - def setdatetimearray(self, value): - print(repr(value)) - self.assertEqual(type(value), list) - self.assertEqual(type(value[0]), datetime.datetime) - return value - - @expose(NestedOuter) - @validate(NestedOuter) - def setnested(self, value): - print(repr(value)) - self.assertEqual(type(value), NestedOuter) - return value - - @expose([NestedOuter]) - @validate([NestedOuter]) - def setnestedarray(self, value): - print(repr(value)) - self.assertEqual(type(value), list) - self.assertEqual(type(value[0]), NestedOuter) - return value - - @expose({wsme.types.bytes: NestedOuter}) - @validate({wsme.types.bytes: NestedOuter}) - def setnesteddict(self, value): - print(repr(value)) - self.assertEqual(type(value), dict) - self.assertEqual(type(list(value.keys())[0]), wsme.types.bytes) - self.assertEqual(type(list(value.values())[0]), NestedOuter) - return value - - @expose(myenumtype) - @validate(myenumtype) - def setenum(self, value): - print(value) - self.assertEqual(type(value), wsme.types.bytes) - return value - - @expose(NamedAttrsObject) - @validate(NamedAttrsObject) - def setnamedattrsobj(self, value): - print(value) - self.assertEqual(type(value), NamedAttrsObject) - self.assertEqual(value.attr_1, 10) - self.assertEqual(value.attr_2, 20) - return value - - @expose(CustomObject) - @validate(CustomObject) - def setcustomobject(self, value): - self.assertIsInstance(value, CustomObject) - self.assertIsInstance(value.name, wsme.types.text) - self.assertIsInstance(value.aint, int) - return value - - @expose(ExtendedInt()) - @validate(ExtendedInt()) - def setextendedint(self, value): - self.assertEqual(isinstance(value, ExtendedInt.basetype), True) - return value - - -class BodyTypes(object): - def assertEqual(self, a, b): - if not (a == b): - raise AssertionError('%s != %s' % (a, b)) - - @expose(int, body={wsme.types.text: int}) - @validate(int) - def setdict(self, body): - print(body) - self.assertEqual(type(body), dict) - self.assertEqual(type(body['test']), int) - self.assertEqual(body['test'], 10) - return body['test'] - - @expose(int, body=[int]) - @validate(int) - def setlist(self, body): - print(body) - self.assertEqual(type(body), list) - self.assertEqual(type(body[0]), int) - self.assertEqual(body[0], 10) - return body[0] - - -class WithErrors(object): - @expose() - def divide_by_zero(self): - 1 / 0 - - -class MiscFunctions(object): - @expose(int) - @validate(int, int) - def multiply(self, a, b): - return a * b - - -class WSTestRoot(WSRoot): - argtypes = ArgTypes() - returntypes = ReturnTypes() - bodytypes = BodyTypes() - witherrors = WithErrors() - nested = NestedOuterApi() - misc = MiscFunctions() - - def reset(self): - self._touched = False - - @expose() - def touch(self): - self._touched = True - - -class ProtocolTestCase(unittest.TestCase): - protocol_options = {} - - def assertTypedEquals(self, a, b, convert): - if isinstance(a, six.string_types): - a = convert(a) - if isinstance(b, six.string_types): - b = convert(b) - self.assertEqual(a, b) - - def assertDateEquals(self, a, b): - self.assertTypedEquals(a, b, wsme.utils.parse_isodate) - - def assertTimeEquals(self, a, b): - self.assertTypedEquals(a, b, wsme.utils.parse_isotime) - - def assertDateTimeEquals(self, a, b): - self.assertTypedEquals(a, b, wsme.utils.parse_isodatetime) - - def assertIntEquals(self, a, b): - self.assertTypedEquals(a, b, int) - - def assertFloatEquals(self, a, b): - self.assertTypedEquals(a, b, float) - - def assertDecimalEquals(self, a, b): - self.assertTypedEquals(a, b, decimal.Decimal) - - def setUp(self): - if self.__class__.__name__ != 'ProtocolTestCase': - self.root = WSTestRoot() - self.root.getapi() - self.root.addprotocol(self.protocol, **self.protocol_options) - - self.app = TestApp(self.root.wsgiapp()) - - def test_invalid_path(self): - try: - res = self.call('invalid_function') - print(res) - assert "No error raised" - except CallException as e: - self.assertEqual(e.faultcode, 'Client') - self.assertEqual(e.faultstring.lower(), - u('unknown function name: invalid_function')) - - def test_serverside_error(self): - try: - res = self.call('witherrors/divide_by_zero') - print(res) - assert "No error raised" - except CallException as e: - self.assertEqual(e.faultcode, 'Server') - self.assertEqual(e.faultstring, zerodivisionerrormsg) - assert e.debuginfo is not None - - def test_serverside_error_nodebug(self): - self.root._debug = False - try: - res = self.call('witherrors/divide_by_zero') - print(res) - assert "No error raised" - except CallException as e: - self.assertEqual(e.faultcode, 'Server') - self.assertEqual(e.faultstring, zerodivisionerrormsg) - assert e.debuginfo is None - - def test_touch(self): - r = self.call('touch') - assert r is None, r - - def test_return_bytes(self): - r = self.call('returntypes/getbytes', _rt=wsme.types.bytes) - self.assertEqual(r, b('astring')) - - def test_return_text(self): - r = self.call('returntypes/gettext', _rt=wsme.types.text) - self.assertEqual(r, u('\xe3\x81\xae')) - - def test_return_int(self): - r = self.call('returntypes/getint') - self.assertIntEquals(r, 2) - - def test_return_float(self): - r = self.call('returntypes/getfloat') - self.assertFloatEquals(r, 3.14159265) - - def test_return_decimal(self): - r = self.call('returntypes/getdecimal') - self.assertDecimalEquals(r, '3.14159265') - - def test_return_bool_true(self): - r = self.call('returntypes/getbooltrue', _rt=bool) - assert r - - def test_return_bool_false(self): - r = self.call('returntypes/getboolfalse', _rt=bool) - assert not r - - def test_return_date(self): - r = self.call('returntypes/getdate') - self.assertDateEquals(r, datetime.date(1994, 1, 26)) - - def test_return_time(self): - r = self.call('returntypes/gettime') - self.assertTimeEquals(r, datetime.time(12)) - - def test_return_datetime(self): - r = self.call('returntypes/getdatetime') - self.assertDateTimeEquals(r, datetime.datetime(1994, 1, 26, 12)) - - def test_return_binary(self): - r = self.call('returntypes/getbinary', _rt=wsme.types.binary) - self.assertEqual(r, binarysample) - - def test_return_nested(self): - r = self.call('returntypes/getnested', _rt=NestedOuter) - self.assertEqual(r, {'inner': {'aint': 0}}) - - def test_return_bytesarray(self): - r = self.call('returntypes/getbytesarray', _rt=[six.binary_type]) - self.assertEqual(r, [b('A'), b('B'), b('C')]) - - def test_return_nestedarray(self): - r = self.call('returntypes/getnestedarray', _rt=[NestedOuter]) - self.assertEqual(r, [{'inner': {'aint': 0}}, {'inner': {'aint': 0}}]) - - def test_return_nesteddict(self): - r = self.call('returntypes/getnesteddict', - _rt={wsme.types.bytes: NestedOuter}) - self.assertEqual(r, { - b('a'): {'inner': {'aint': 0}}, - b('b'): {'inner': {'aint': 0}} - }) - - def test_return_objectarrayattribute(self): - r = self.call('returntypes/getobjectarrayattribute', _rt=NestedOuter) - self.assertEqual(r, { - 'inner': {'aint': 0}, - 'inner_array': [{'aint': 12}, {'aint': 13}] - }) - - def test_return_objectdictattribute(self): - r = self.call('returntypes/getobjectdictattribute', _rt=NestedOuter) - self.assertEqual(r, { - 'inner': {'aint': 0}, - 'inner_dict': { - '12': {'aint': 12}, - '13': {'aint': 13} - } - }) - - def test_return_enum(self): - r = self.call('returntypes/getenum', _rt=myenumtype) - self.assertEqual(r, b('v2'), r) - - def test_return_namedattrsobj(self): - r = self.call('returntypes/getnamedattrsobj', _rt=NamedAttrsObject) - self.assertEqual(r, {'attr.1': 5, 'attr.2': 6}) - - def test_setbytes(self): - assert self.call('argtypes/setbytes', value=b('astring'), - _rt=wsme.types.bytes) == b('astring') - - def test_settext(self): - assert self.call('argtypes/settext', value=u('\xe3\x81\xae'), - _rt=wsme.types.text) == u('\xe3\x81\xae') - - def test_settext_empty(self): - assert self.call('argtypes/settext', value=u(''), - _rt=wsme.types.text) == u('') - - def test_settext_none(self): - self.assertEqual( - None, - self.call('argtypes/settextnone', value=None, _rt=wsme.types.text) - ) - - def test_setint(self): - r = self.call('argtypes/setint', value=3, _rt=int) - self.assertEqual(r, 3) - - def test_setfloat(self): - assert self.call('argtypes/setfloat', value=3.54, - _rt=float) == 3.54 - - def test_setbool_true(self): - r = self.call('argtypes/setbool', value=True, _rt=bool) - assert r - - def test_setbool_false(self): - r = self.call('argtypes/setbool', value=False, _rt=bool) - assert not r - - def test_setdecimal(self): - value = decimal.Decimal('3.14') - assert self.call('argtypes/setdecimal', value=value, - _rt=decimal.Decimal) == value - - def test_setdate(self): - value = datetime.date(2008, 4, 6) - r = self.call('argtypes/setdate', value=value, - _rt=datetime.date) - self.assertEqual(r, value) - - def test_settime(self): - value = datetime.time(12, 12, 15) - r = self.call('argtypes/settime', value=value, - _rt=datetime.time) - self.assertEqual(r, datetime.time(12, 12, 15)) - - def test_setdatetime(self): - value = datetime.datetime(2008, 4, 6, 12, 12, 15) - r = self.call('argtypes/setdatetime', value=value, - _rt=datetime.datetime) - self.assertEqual(r, datetime.datetime(2008, 4, 6, 12, 12, 15)) - - def test_setbinary(self): - value = binarysample - r = self.call('argtypes/setbinary', value=(value, wsme.types.binary), - _rt=wsme.types.binary) == value - print(r) - - def test_setnested(self): - value = {'inner': {'aint': 54}} - r = self.call('argtypes/setnested', - value=(value, NestedOuter), - _rt=NestedOuter) - self.assertEqual(r, value) - - def test_setnested_nullobj(self): - value = {'inner': None} - r = self.call( - 'argtypes/setnested', - value=(value, NestedOuter), - _rt=NestedOuter - ) - self.assertEqual(r, value) - - def test_setbytesarray(self): - value = [b("1"), b("2"), b("three")] - r = self.call('argtypes/setbytesarray', - value=(value, [wsme.types.bytes]), - _rt=[wsme.types.bytes]) - self.assertEqual(r, value) - - def test_settextarray(self): - value = [u("1")] - r = self.call('argtypes/settextarray', - value=(value, [wsme.types.text]), - _rt=[wsme.types.text]) - self.assertEqual(r, value) - - def test_setdatetimearray(self): - value = [ - datetime.datetime(2008, 3, 6, 12, 12, 15), - datetime.datetime(2008, 4, 6, 2, 12, 15), - ] - r = self.call('argtypes/setdatetimearray', - value=(value, [datetime.datetime]), - _rt=[datetime.datetime]) - self.assertEqual(r, value) - - def test_setnestedarray(self): - value = [ - {'inner': {'aint': 54}}, - {'inner': {'aint': 55}}, - ] - r = self.call('argtypes/setnestedarray', - value=(value, [NestedOuter]), - _rt=[NestedOuter]) - self.assertEqual(r, value) - - def test_setnesteddict(self): - value = { - b('o1'): {'inner': {'aint': 54}}, - b('o2'): {'inner': {'aint': 55}}, - } - r = self.call('argtypes/setnesteddict', - value=(value, {six.binary_type: NestedOuter}), - _rt={six.binary_type: NestedOuter}) - print(r) - self.assertEqual(r, value) - - def test_setenum(self): - value = b('v1') - r = self.call('argtypes/setenum', value=value, - _rt=myenumtype) - self.assertEqual(r, value) - - def test_setnamedattrsobj(self): - value = {'attr.1': 10, 'attr.2': 20} - r = self.call('argtypes/setnamedattrsobj', - value=(value, NamedAttrsObject), - _rt=NamedAttrsObject) - self.assertEqual(r, value) - - def test_nested_api(self): - r = self.call('nested/inner/deepfunction', _rt=bool) - assert r is True - - def test_missing_argument(self): - try: - r = self.call('argtypes/setdatetime') - print(r) - assert "No error raised" - except CallException as e: - self.assertEqual(e.faultcode, 'Client') - self.assertEqual(e.faultstring, u('Missing argument: "value"')) - - def test_misc_multiply(self): - self.assertEqual(self.call('misc/multiply', a=5, b=2, _rt=int), 10) - - def test_html_format(self): - res = self.call('argtypes/setdatetime', _accept="text/html", - _no_result_decode=True) - self.assertEqual(res.content_type, 'text/html') - - -class RestOnlyProtocolTestCase(ProtocolTestCase): - def test_body_list(self): - r = self.call('bodytypes/setlist', body=([10], [int]), _rt=int) - self.assertEqual(r, 10) - - def test_body_dict(self): - r = self.call('bodytypes/setdict', - body=({'test': 10}, {wsme.types.text: int}), - _rt=int) - self.assertEqual(r, 10) diff --git a/wsme/tests/test_api.py b/wsme/tests/test_api.py deleted file mode 100644 index fc1e157..0000000 --- a/wsme/tests/test_api.py +++ /dev/null @@ -1,419 +0,0 @@ -# encoding=utf8 - -from six import b - -try: - import unittest2 as unittest -except ImportError: - import unittest -import webtest - -from wsme import WSRoot, expose, validate -from wsme.rest import scan_api -from wsme import types -from wsme import exc -import wsme.api as wsme_api -import wsme.types - -from wsme.tests.test_protocols import DummyProtocol - - -class TestController(unittest.TestCase): - def test_expose(self): - class MyWS(WSRoot): - @expose(int) - def getint(self): - return 1 - - assert MyWS.getint._wsme_definition.return_type == int - - def test_validate(self): - class ComplexType(object): - attr = int - - class MyWS(object): - @expose(int) - @validate(int, int, int) - def add(self, a, b, c=0): - return a + b + c - - @expose(bool) - @validate(ComplexType) - def setcplx(self, obj): - pass - - MyWS.add._wsme_definition.resolve_types(wsme.types.registry) - MyWS.setcplx._wsme_definition.resolve_types(wsme.types.registry) - args = MyWS.add._wsme_definition.arguments - - assert args[0].name == 'a' - assert args[0].datatype == int - assert args[0].mandatory - assert args[0].default is None - - assert args[1].name == 'b' - assert args[1].datatype == int - assert args[1].mandatory - assert args[1].default is None - - assert args[2].name == 'c' - assert args[2].datatype == int - assert not args[2].mandatory - assert args[2].default == 0 - - assert types.iscomplex(ComplexType) - - def test_validate_enum_with_none(self): - class Version(object): - number = types.Enum(str, 'v1', 'v2', None) - - class MyWS(WSRoot): - @expose(str) - @validate(Version) - def setcplx(self, version): - pass - - r = MyWS(['restjson']) - app = webtest.TestApp(r.wsgiapp()) - res = app.post_json('/setcplx', params={'version': {'number': 'arf'}}, - expect_errors=True, - headers={'Accept': 'application/json'}) - self.assertTrue( - res.json_body['faultstring'].startswith( - "Invalid input for field/attribute number. Value: 'arf'. \ -Value should be one of:")) - self.assertIn('v1', res.json_body['faultstring']) - self.assertIn('v2', res.json_body['faultstring']) - self.assertIn('None', res.json_body['faultstring']) - self.assertEqual(res.status_int, 400) - - def test_validate_enum_with_wrong_type(self): - class Version(object): - number = types.Enum(str, 'v1', 'v2', None) - - class MyWS(WSRoot): - @expose(str) - @validate(Version) - def setcplx(self, version): - pass - - r = MyWS(['restjson']) - app = webtest.TestApp(r.wsgiapp()) - res = app.post_json('/setcplx', params={'version': {'number': 1}}, - expect_errors=True, - headers={'Accept': 'application/json'}) - self.assertTrue( - res.json_body['faultstring'].startswith( - "Invalid input for field/attribute number. Value: '1'. \ -Value should be one of:")) - self.assertIn('v1', res.json_body['faultstring']) - self.assertIn('v2', res.json_body['faultstring']) - self.assertIn('None', res.json_body['faultstring']) - self.assertEqual(res.status_int, 400) - - def test_scan_api(self): - class NS(object): - @expose(int) - @validate(int, int) - def multiply(self, a, b): - return a * b - - class MyRoot(WSRoot): - ns = NS() - - r = MyRoot() - - api = list(scan_api(r)) - assert len(api) == 1 - path, fd, args = api[0] - assert path == ['ns', 'multiply'] - assert fd._wsme_definition.name == 'multiply' - assert args == [] - - def test_scan_subclass(self): - class MyRoot(WSRoot): - class SubClass(object): - pass - - r = MyRoot() - api = list(scan_api(r)) - - assert len(api) == 0 - - def test_scan_api_too_deep(self): - class Loop(object): - pass - - ell = Loop() - for i in range(0, 21): - nl = Loop() - nl.ell = ell - ell = nl - - class MyRoot(WSRoot): - loop = ell - - r = MyRoot() - - try: - list(scan_api(r)) - assert False, "ValueError not raised" - except ValueError as e: - assert str(e).startswith("Path is too long") - - def test_handle_request(self): - class MyRoot(WSRoot): - @expose() - def touch(self): - pass - - p = DummyProtocol() - r = MyRoot(protocols=[p]) - - app = webtest.TestApp(r.wsgiapp()) - - res = app.get('/') - - assert p.lastreq.path == '/' - assert p.hits == 1 - - res = app.get('/touch?wsmeproto=dummy') - - assert p.lastreq.path == '/touch' - assert p.hits == 2 - - class NoPathProto(DummyProtocol): - def extract_path(self, request): - return None - - p = NoPathProto() - r = MyRoot(protocols=[p]) - - app = webtest.TestApp(r.wsgiapp()) - - res = app.get('/', expect_errors=True) - print(res.status, res.body) - assert res.status_int == 400 - - def test_no_available_protocol(self): - r = WSRoot() - - app = webtest.TestApp(r.wsgiapp()) - - res = app.get('/', expect_errors=True) - print(res.status_int) - assert res.status_int == 406 - print(res.body) - assert res.body.find( - b("None of the following protocols can handle this request")) != -1 - - def test_return_content_type_guess(self): - class DummierProto(DummyProtocol): - content_types = ['text/xml', 'text/plain'] - - r = WSRoot([DummierProto()]) - - app = webtest.TestApp(r.wsgiapp()) - - res = app.get('/', expect_errors=True, headers={ - 'Accept': 'text/xml,q=0.8'}) - assert res.status_int == 400 - assert res.content_type == 'text/xml', res.content_type - - res = app.get('/', expect_errors=True, headers={ - 'Accept': 'text/plain'}) - assert res.status_int == 400 - assert res.content_type == 'text/plain', res.content_type - - def test_double_expose(self): - try: - class MyRoot(WSRoot): - @expose() - @expose() - def atest(self): - pass - assert False, "A ValueError should have been raised" - except ValueError: - pass - - def test_multiple_expose(self): - class MyRoot(WSRoot): - def multiply(self, a, b): - return a * b - - mul_int = expose(int, int, int, wrap=True)(multiply) - - mul_float = expose( - float, float, float, - wrap=True)(multiply) - - mul_string = expose( - wsme.types.text, wsme.types.text, int, - wrap=True)(multiply) - - r = MyRoot(['restjson']) - - app = webtest.TestApp(r.wsgiapp()) - - res = app.get('/mul_int?a=2&b=5', headers={ - 'Accept': 'application/json' - }) - - self.assertEqual(res.body, b('10')) - - res = app.get('/mul_float?a=1.2&b=2.9', headers={ - 'Accept': 'application/json' - }) - - self.assertEqual(res.body, b('3.48')) - - res = app.get('/mul_string?a=hello&b=2', headers={ - 'Accept': 'application/json' - }) - - self.assertEqual(res.body, b('"hellohello"')) - - def test_wsattr_mandatory(self): - class ComplexType(object): - attr = wsme.types.wsattr(int, mandatory=True) - - class MyRoot(WSRoot): - @expose(int, body=ComplexType) - @validate(ComplexType) - def clx(self, a): - return a.attr - - r = MyRoot(['restjson']) - app = webtest.TestApp(r.wsgiapp()) - res = app.post_json('/clx', params={}, expect_errors=True, - headers={'Accept': 'application/json'}) - self.assertEqual(res.status_int, 400) - - def test_wsattr_readonly(self): - class ComplexType(object): - attr = wsme.types.wsattr(int, readonly=True) - - class MyRoot(WSRoot): - @expose(int, body=ComplexType) - @validate(ComplexType) - def clx(self, a): - return a.attr - - r = MyRoot(['restjson']) - app = webtest.TestApp(r.wsgiapp()) - res = app.post_json('/clx', params={'attr': 1005}, expect_errors=True, - headers={'Accept': 'application/json'}) - self.assertIn('Cannot set read only field.', - res.json_body['faultstring']) - self.assertIn('1005', res.json_body['faultstring']) - self.assertEqual(res.status_int, 400) - - def test_wsattr_default(self): - class ComplexType(object): - attr = wsme.types.wsattr(wsme.types.Enum(str, 'or', 'and'), - default='and') - - class MyRoot(WSRoot): - @expose(int) - @validate(ComplexType) - def clx(self, a): - return a.attr - - r = MyRoot(['restjson']) - app = webtest.TestApp(r.wsgiapp()) - res = app.post_json('/clx', params={}, expect_errors=True, - headers={'Accept': 'application/json'}) - self.assertEqual(res.status_int, 400) - - def test_wsproperty_mandatory(self): - class ComplexType(object): - def foo(self): - pass - - attr = wsme.types.wsproperty(int, foo, foo, mandatory=True) - - class MyRoot(WSRoot): - @expose(int, body=ComplexType) - @validate(ComplexType) - def clx(self, a): - return a.attr - - r = MyRoot(['restjson']) - app = webtest.TestApp(r.wsgiapp()) - res = app.post_json('/clx', params={}, expect_errors=True, - headers={'Accept': 'application/json'}) - self.assertEqual(res.status_int, 400) - - def test_validate_enum_mandatory(self): - class Version(object): - number = wsme.types.wsattr(wsme.types.Enum(str, 'v1', 'v2'), - mandatory=True) - - class MyWS(WSRoot): - @expose(str) - @validate(Version) - def setcplx(self, version): - pass - - r = MyWS(['restjson']) - app = webtest.TestApp(r.wsgiapp()) - res = app.post_json('/setcplx', params={'version': {}}, - expect_errors=True, - headers={'Accept': 'application/json'}) - self.assertEqual(res.status_int, 400) - - -class TestFunctionDefinition(unittest.TestCase): - - def test_get_arg(self): - def myfunc(self): - pass - - fd = wsme_api.FunctionDefinition(wsme_api.FunctionDefinition) - fd.arguments.append(wsme_api.FunctionArgument('a', int, True, None)) - - assert fd.get_arg('a').datatype is int - assert fd.get_arg('b') is None - - -class TestFormatException(unittest.TestCase): - - def _test_format_exception(self, exception, debug=False): - fake_exc_info = (None, exception, None) - return wsme_api.format_exception(fake_exc_info, debug=debug) - - def test_format_client_exception(self): - faultstring = 'boom' - ret = self._test_format_exception(exc.ClientSideError(faultstring)) - self.assertIsNone(ret['debuginfo']) - self.assertEqual('Client', ret['faultcode']) - self.assertEqual(faultstring, ret['faultstring']) - - def test_format_client_exception_unicode(self): - faultstring = u'\xc3\xa3o' - ret = self._test_format_exception(exc.ClientSideError(faultstring)) - self.assertIsNone(ret['debuginfo']) - self.assertEqual('Client', ret['faultcode']) - self.assertEqual(faultstring, ret['faultstring']) - - def test_format_server_exception(self): - faultstring = 'boom' - ret = self._test_format_exception(Exception(faultstring)) - self.assertIsNone(ret['debuginfo']) - self.assertEqual('Server', ret['faultcode']) - self.assertEqual(faultstring, ret['faultstring']) - - def test_format_server_exception_unicode(self): - faultstring = u'\xc3\xa3o' - ret = self._test_format_exception(Exception(faultstring)) - self.assertIsNone(ret['debuginfo']) - self.assertEqual('Server', ret['faultcode']) - self.assertEqual(faultstring, ret['faultstring']) - - def test_format_server_exception_debug(self): - faultstring = 'boom' - ret = self._test_format_exception(Exception(faultstring), debug=True) - # assert debuginfo is populated - self.assertIsNotNone(ret['debuginfo']) - self.assertEqual('Server', ret['faultcode']) - self.assertEqual(faultstring, ret['faultstring']) diff --git a/wsme/tests/test_exc.py b/wsme/tests/test_exc.py deleted file mode 100644 index ba903fb..0000000 --- a/wsme/tests/test_exc.py +++ /dev/null @@ -1,40 +0,0 @@ -# encoding=utf8 - -from wsme.exc import (ClientSideError, InvalidInput, MissingArgument, - UnknownArgument) -from six import u - - -def test_clientside_error(): - e = ClientSideError("Test") - - assert e.faultstring == u("Test") - - -def test_unicode_clientside_error(): - e = ClientSideError(u("\u30d5\u30a1\u30b7\u30ea")) - - assert e.faultstring == u("\u30d5\u30a1\u30b7\u30ea") - - -def test_invalidinput(): - e = InvalidInput('field', 'badvalue', "error message") - - assert e.faultstring == u( - "Invalid input for field/attribute field. Value: 'badvalue'. " - "error message" - ), e.faultstring - - -def test_missingargument(): - e = MissingArgument('argname', "error message") - - assert e.faultstring == \ - u('Missing argument: "argname": error message'), e.faultstring - - -def test_unknownargument(): - e = UnknownArgument('argname', "error message") - - assert e.faultstring == \ - u('Unknown argument: "argname": error message'), e.faultstring diff --git a/wsme/tests/test_protocols.py b/wsme/tests/test_protocols.py deleted file mode 100644 index f4b7270..0000000 --- a/wsme/tests/test_protocols.py +++ /dev/null @@ -1,70 +0,0 @@ -# encoding=utf8 - -import unittest - -from wsme import WSRoot -from wsme.protocol import getprotocol, CallContext, Protocol -import wsme.protocol - - -class DummyProtocol(Protocol): - name = 'dummy' - content_types = ['', None] - - def __init__(self): - self.hits = 0 - - def accept(self, req): - return True - - def iter_calls(self, req): - yield CallContext(req) - - def extract_path(self, context): - return ['touch'] - - def read_arguments(self, context): - self.lastreq = context.request - self.hits += 1 - return {} - - def encode_result(self, context, result): - return str(result) - - def encode_error(self, context, infos): - return str(infos) - - -def test_getprotocol(): - try: - getprotocol('invalid') - assert False, "ValueError was not raised" - except ValueError: - pass - - -class TestProtocols(unittest.TestCase): - def test_register_protocol(self): - wsme.protocol.register_protocol(DummyProtocol) - assert wsme.protocol.registered_protocols['dummy'] == DummyProtocol - - r = WSRoot() - assert len(r.protocols) == 0 - - r.addprotocol('dummy') - assert len(r.protocols) == 1 - assert r.protocols[0].__class__ == DummyProtocol - - r = WSRoot(['dummy']) - assert len(r.protocols) == 1 - assert r.protocols[0].__class__ == DummyProtocol - - def test_Protocol(self): - p = wsme.protocol.Protocol() - assert p.iter_calls(None) is None - assert p.extract_path(None) is None - assert p.read_arguments(None) is None - assert p.encode_result(None, None) is None - assert p.encode_sample_value(None, None) == ('none', 'N/A') - assert p.encode_sample_params(None) == ('none', 'N/A') - assert p.encode_sample_result(None, None) == ('none', 'N/A') diff --git a/wsme/tests/test_protocols_commons.py b/wsme/tests/test_protocols_commons.py deleted file mode 100644 index af5aa05..0000000 --- a/wsme/tests/test_protocols_commons.py +++ /dev/null @@ -1,159 +0,0 @@ -# encoding=utf8 - -import datetime -import unittest - -from wsme.api import FunctionArgument, FunctionDefinition -from wsme.rest.args import from_param, from_params, args_from_args -from wsme.exc import InvalidInput - -from wsme.types import UserType, Unset, ArrayType, DictType, Base - - -class MyBaseType(Base): - test = str - - -class MyUserType(UserType): - basetype = str - - -class DictBasedUserType(UserType): - basetype = DictType(int, int) - - -class TestProtocolsCommons(unittest.TestCase): - def test_from_param_date(self): - assert from_param(datetime.date, '2008-02-28') == \ - datetime.date(2008, 2, 28) - - def test_from_param_time(self): - assert from_param(datetime.time, '12:14:56') == \ - datetime.time(12, 14, 56) - - def test_from_param_datetime(self): - assert from_param(datetime.datetime, '2009-12-23T12:14:56') == \ - datetime.datetime(2009, 12, 23, 12, 14, 56) - - def test_from_param_usertype(self): - assert from_param(MyUserType(), 'test') == 'test' - - def test_from_params_empty(self): - assert from_params(str, {}, '', set()) is Unset - - def test_from_params_native_array(self): - class params(dict): - def getall(self, path): - return ['1', '2'] - p = params({'a': []}) - assert from_params(ArrayType(int), p, 'a', set()) == [1, 2] - - def test_from_params_empty_array(self): - assert from_params(ArrayType(int), {}, 'a', set()) is Unset - - def test_from_params_dict(self): - value = from_params( - DictType(int, str), - {'a[2]': 'a2', 'a[3]': 'a3'}, - 'a', - set() - ) - assert value == {2: 'a2', 3: 'a3'}, value - - def test_from_params_dict_unset(self): - assert from_params(DictType(int, str), {}, 'a', set()) is Unset - - def test_from_params_usertype(self): - value = from_params( - DictBasedUserType(), - {'a[2]': '2'}, - 'a', - set() - ) - self.assertEqual(value, {2: 2}) - - def test_args_from_args_usertype(self): - - class FakeType(UserType): - name = 'fake-type' - basetype = int - - fake_type = FakeType() - fd = FunctionDefinition(FunctionDefinition) - fd.arguments.append(FunctionArgument('fake-arg', fake_type, True, 0)) - - new_args = args_from_args(fd, [1], {}) - self.assertEqual([1], new_args[0]) - - # can't convert str to int - try: - args_from_args(fd, ['invalid-argument'], {}) - except InvalidInput as e: - assert fake_type.name in str(e) - else: - self.fail('Should have thrown an InvalidInput') - - def test_args_from_args_custom_exc(self): - - class FakeType(UserType): - name = 'fake-type' - basetype = int - - def validate(self, value): - if value < 10: - raise ValueError('should be greater than 10') - - def frombasetype(self, value): - self.validate(value) - - fake_type = FakeType() - fd = FunctionDefinition(FunctionDefinition) - fd.arguments.append(FunctionArgument('fake-arg', fake_type, True, 0)) - - try: - args_from_args(fd, [9], {}) - except InvalidInput as e: - assert fake_type.name in str(e) - assert 'Error: should be greater than 10' in str(e) - else: - self.fail('Should have thrown an InvalidInput') - - def test_args_from_args_array_type(self): - fake_type = ArrayType(MyBaseType) - fd = FunctionDefinition(FunctionDefinition) - fd.arguments.append(FunctionArgument('fake-arg', fake_type, True, [])) - try: - args_from_args(fd, [['invalid-argument']], {}) - except InvalidInput as e: - assert ArrayType.__name__ in str(e) - else: - self.fail('Should have thrown an InvalidInput') - - -class ArgTypeConversion(unittest.TestCase): - - def test_int_zero(self): - self.assertEqual(0, from_param(int, 0)) - self.assertEqual(0, from_param(int, '0')) - - def test_int_nonzero(self): - self.assertEqual(1, from_param(int, 1)) - self.assertEqual(1, from_param(int, '1')) - - def test_int_none(self): - self.assertEqual(None, from_param(int, None)) - - def test_float_zero(self): - self.assertEqual(0.0, from_param(float, 0)) - self.assertEqual(0.0, from_param(float, 0.0)) - self.assertEqual(0.0, from_param(float, '0')) - self.assertEqual(0.0, from_param(float, '0.0')) - - def test_float_nonzero(self): - self.assertEqual(1.0, from_param(float, 1)) - self.assertEqual(1.0, from_param(float, 1.0)) - self.assertEqual(1.0, from_param(float, '1')) - self.assertEqual(1.0, from_param(float, '1.0')) - - def test_float_none(self): - self.assertEqual(None, from_param(float, None)) diff --git a/wsme/tests/test_restjson.py b/wsme/tests/test_restjson.py deleted file mode 100644 index 7afbb86..0000000 --- a/wsme/tests/test_restjson.py +++ /dev/null @@ -1,779 +0,0 @@ -import base64 -import datetime -import decimal - -import wsme.tests.protocol - -try: - import simplejson as json -except ImportError: - import json # noqa - -from wsme.rest.json import fromjson, tojson, parse -from wsme.utils import parse_isodatetime, parse_isotime, parse_isodate -from wsme.types import isarray, isdict, isusertype, register_type -from wsme.types import UserType, ArrayType, DictType -from wsme.rest import expose, validate -from wsme.exc import ClientSideError, InvalidInput - - -import six -from six import b, u - -if six.PY3: - from urllib.parse import urlencode -else: - from urllib import urlencode # noqa - - -def prepare_value(value, datatype): - if isinstance(datatype, list): - return [prepare_value(item, datatype[0]) for item in value] - if isinstance(datatype, dict): - key_type, value_type = list(datatype.items())[0] - return dict(( - (prepare_value(item[0], key_type), - prepare_value(item[1], value_type)) - for item in value.items() - )) - if datatype in (datetime.date, datetime.time, datetime.datetime): - return value.isoformat() - if datatype == decimal.Decimal: - return str(value) - if datatype == wsme.types.binary: - return base64.encodestring(value).decode('ascii') - if datatype == wsme.types.bytes: - return value.decode('ascii') - return value - - -def prepare_result(value, datatype): - print(value, datatype) - if value is None: - return None - if datatype == wsme.types.binary: - return base64.decodestring(value.encode('ascii')) - if isusertype(datatype): - datatype = datatype.basetype - if isinstance(datatype, list): - return [prepare_result(item, datatype[0]) for item in value] - if isarray(datatype): - return [prepare_result(item, datatype.item_type) for item in value] - if isinstance(datatype, dict): - return dict(( - (prepare_result(item[0], list(datatype.keys())[0]), - prepare_result(item[1], list(datatype.values())[0])) - for item in value.items() - )) - if isdict(datatype): - return dict(( - (prepare_result(item[0], datatype.key_type), - prepare_result(item[1], datatype.value_type)) - for item in value.items() - )) - if datatype == datetime.date: - return parse_isodate(value) - if datatype == datetime.time: - return parse_isotime(value) - if datatype == datetime.datetime: - return parse_isodatetime(value) - if hasattr(datatype, '_wsme_attributes'): - for attr in datatype._wsme_attributes: - if attr.key not in value: - continue - value[attr.key] = prepare_result(value[attr.key], attr.datatype) - return value - if datatype == wsme.types.bytes: - return value.encode('ascii') - if type(value) != datatype: - print(type(value), datatype) - return datatype(value) - return value - - -class CustomInt(UserType): - basetype = int - name = "custom integer" - - -class Obj(wsme.types.Base): - id = int - name = wsme.types.text - - -class NestedObj(wsme.types.Base): - o = Obj - - -class CRUDResult(object): - data = Obj - message = wsme.types.text - - def __init__(self, data=wsme.types.Unset, message=wsme.types.Unset): - self.data = data - self.message = message - - -class MiniCrud(object): - @expose(CRUDResult, method='PUT') - @validate(Obj) - def create(self, data): - print(repr(data)) - return CRUDResult(data, u('create')) - - @expose(CRUDResult, method='GET', ignore_extra_args=True) - @validate(Obj) - def read(self, ref): - print(repr(ref)) - if ref.id == 1: - ref.name = u('test') - return CRUDResult(ref, u('read')) - - @expose(CRUDResult, method='POST') - @validate(Obj) - def update(self, data): - print(repr(data)) - return CRUDResult(data, u('update')) - - @expose(CRUDResult, wsme.types.text, body=Obj) - def update_with_body(self, msg, data): - print(repr(data)) - return CRUDResult(data, msg) - - @expose(CRUDResult, method='DELETE') - @validate(Obj) - def delete(self, ref): - print(repr(ref)) - if ref.id == 1: - ref.name = u('test') - return CRUDResult(ref, u('delete')) - - -wsme.tests.protocol.WSTestRoot.crud = MiniCrud() - - -class TestRestJson(wsme.tests.protocol.RestOnlyProtocolTestCase): - protocol = 'restjson' - - def call(self, fpath, _rt=None, _accept=None, _no_result_decode=False, - body=None, **kw): - if body: - if isinstance(body, tuple): - body, datatype = body - else: - datatype = type(body) - body = prepare_value(body, datatype) - content = json.dumps(body) - else: - for key in kw: - if isinstance(kw[key], tuple): - value, datatype = kw[key] - else: - value = kw[key] - datatype = type(value) - kw[key] = prepare_value(value, datatype) - content = json.dumps(kw) - headers = { - 'Content-Type': 'application/json', - } - if _accept is not None: - headers["Accept"] = _accept - res = self.app.post( - '/' + fpath, - content, - headers=headers, - expect_errors=True) - print("Received:", res.body) - - if _no_result_decode: - return res - - r = json.loads(res.text) - if res.status_int == 200: - if _rt and r: - r = prepare_result(r, _rt) - return r - else: - raise wsme.tests.protocol.CallException( - r['faultcode'], - r['faultstring'], - r.get('debuginfo') - ) - - return json.loads(res.text) - - def test_fromjson(self): - assert fromjson(str, None) is None - - def test_keyargs(self): - r = self.app.get('/argtypes/setint.json?value=2') - print(r) - assert json.loads(r.text) == 2 - - nestedarray = 'value[0].inner.aint=54&value[1].inner.aint=55' - r = self.app.get('/argtypes/setnestedarray.json?' + nestedarray) - print(r) - assert json.loads(r.text) == [ - {'inner': {'aint': 54}}, - {'inner': {'aint': 55}}] - - def test_form_urlencoded_args(self): - params = { - 'value[0].inner.aint': 54, - 'value[1].inner.aint': 55 - } - body = urlencode(params) - r = self.app.post( - '/argtypes/setnestedarray.json', - body, - headers={'Content-Type': 'application/x-www-form-urlencoded'} - ) - print(r) - - assert json.loads(r.text) == [ - {'inner': {'aint': 54}}, - {'inner': {'aint': 55}}] - - def test_body_and_params(self): - r = self.app.post('/argtypes/setint.json?value=2', '{"value": 2}', - headers={"Content-Type": "application/json"}, - expect_errors=True) - print(r) - assert r.status_int == 400 - assert json.loads(r.text)['faultstring'] == \ - "Parameter value was given several times" - - def test_inline_body(self): - params = urlencode({'__body__': '{"value": 4}'}) - r = self.app.get('/argtypes/setint.json?' + params) - print(r) - assert json.loads(r.text) == 4 - - def test_empty_body(self): - params = urlencode({'__body__': ''}) - r = self.app.get('/returntypes/getint.json?' + params) - print(r) - assert json.loads(r.text) == 2 - - def test_invalid_content_type_body(self): - r = self.app.post('/argtypes/setint.json', '{"value": 2}', - headers={"Content-Type": "application/invalid"}, - expect_errors=True) - print(r) - assert r.status_int == 415 - assert json.loads(r.text)['faultstring'] == \ - "Unknown mimetype: application/invalid" - - def test_invalid_json_body(self): - r = self.app.post('/argtypes/setint.json', '{"value": 2', - headers={"Content-Type": "application/json"}, - expect_errors=True) - print(r) - assert r.status_int == 400 - assert json.loads(r.text)['faultstring'] == \ - "Request is not in valid JSON format" - - def test_unknown_arg(self): - r = self.app.post('/returntypes/getint.json', '{"a": 2}', - headers={"Content-Type": "application/json"}, - expect_errors=True) - print(r) - assert r.status_int == 400 - assert json.loads(r.text)['faultstring'].startswith( - "Unknown argument:" - ) - - r = self.app.get('/returntypes/getint.json?a=2', expect_errors=True) - print(r) - assert r.status_int == 400 - assert json.loads(r.text)['faultstring'].startswith( - "Unknown argument:" - ) - - def test_set_custom_object(self): - r = self.app.post( - '/argtypes/setcustomobject', - '{"value": {"aint": 2, "name": "test"}}', - headers={"Content-Type": "application/json"} - ) - self.assertEqual(r.status_int, 200) - self.assertEqual(r.json, {'aint': 2, 'name': 'test'}) - - def test_set_extended_int(self): - r = self.app.post( - '/argtypes/setextendedint', - '{"value": 3}', - headers={"Content-Type": "application/json"} - ) - self.assertEqual(r.status_int, 200) - self.assertEqual(r.json, 3) - - def test_unset_attrs(self): - class AType(object): - attr = int - - wsme.types.register_type(AType) - - j = tojson(AType, AType()) - assert j == {} - - def test_array_tojson(self): - assert tojson([int], None) is None - assert tojson([int], []) == [] - assert tojson([str], ['1', '4']) == ['1', '4'] - - def test_dict_tojson(self): - assert tojson({int: str}, None) is None - assert tojson({int: str}, {5: '5'}) == {5: '5'} - - def test_None_tojson(self): - for dt in (datetime.date, datetime.time, datetime.datetime, - decimal.Decimal): - assert tojson(dt, None) is None - - def test_None_fromjson(self): - for dt in (str, int, datetime.date, datetime.time, datetime.datetime, - decimal.Decimal, [int], {int: int}): - assert fromjson(dt, None) is None - - def test_parse_valid_date(self): - j = parse('{"a": "2011-01-01"}', {'a': datetime.date}, False) - assert isinstance(j['a'], datetime.date) - - def test_invalid_root_dict_fromjson(self): - try: - parse('["invalid"]', {'a': ArrayType(str)}, False) - assert False - except Exception as e: - assert isinstance(e, ClientSideError) - assert e.msg == "Request must be a JSON dict" - - def test_invalid_list_fromjson(self): - jlist = "invalid" - try: - parse('{"a": "%s"}' % jlist, {'a': ArrayType(str)}, False) - assert False - except Exception as e: - assert isinstance(e, InvalidInput) - assert e.fieldname == 'a' - assert e.value == jlist - assert e.msg == "Value not a valid list: %s" % jlist - - def test_invalid_dict_fromjson(self): - jdict = "invalid" - try: - parse('{"a": "%s"}' % jdict, {'a': DictType(str, str)}, False) - assert False - except Exception as e: - assert isinstance(e, InvalidInput) - assert e.fieldname == 'a' - assert e.value == jdict - assert e.msg == "Value not a valid dict: %s" % jdict - - def test_invalid_date_fromjson(self): - jdate = "2015-01-invalid" - try: - parse('{"a": "%s"}' % jdate, {'a': datetime.date}, False) - assert False - except Exception as e: - assert isinstance(e, InvalidInput) - assert e.fieldname == 'a' - assert e.value == jdate - assert e.msg == "'%s' is not a legal date value" % jdate - - def test_parse_valid_date_bodyarg(self): - j = parse('"2011-01-01"', {'a': datetime.date}, True) - assert isinstance(j['a'], datetime.date) - - def test_invalid_date_fromjson_bodyarg(self): - jdate = "2015-01-invalid" - try: - parse('"%s"' % jdate, {'a': datetime.date}, True) - assert False - except Exception as e: - assert isinstance(e, InvalidInput) - assert e.fieldname == 'a' - assert e.value == jdate - assert e.msg == "'%s' is not a legal date value" % jdate - - def test_valid_str_to_builtin_fromjson(self): - types = six.integer_types + (bool, float) - value = '2' - for t in types: - for ba in True, False: - jd = '%s' if ba else '{"a": %s}' - i = parse(jd % value, {'a': t}, ba) - self.assertEqual( - i, {'a': t(value)}, - "Parsed value does not correspond for %s: " - "%s != {'a': %s}" % ( - t, repr(i), repr(t(value)) - ) - ) - self.assertIsInstance(i['a'], t) - - def test_valid_int_fromjson(self): - value = 2 - for ba in True, False: - jd = '%d' if ba else '{"a": %d}' - i = parse(jd % value, {'a': int}, ba) - self.assertEqual(i, {'a': 2}) - self.assertIsInstance(i['a'], int) - - def test_valid_num_to_float_fromjson(self): - values = 2, 2.3 - for v in values: - for ba in True, False: - jd = '%f' if ba else '{"a": %f}' - i = parse(jd % v, {'a': float}, ba) - self.assertEqual(i, {'a': float(v)}) - self.assertIsInstance(i['a'], float) - - def test_invalid_str_to_buitin_fromjson(self): - types = six.integer_types + (float, bool) - value = '2a' - for t in types: - for ba in True, False: - jd = '"%s"' if ba else '{"a": "%s"}' - try: - parse(jd % value, {'a': t}, ba) - assert False, ( - "Value '%s' should not parse correctly for %s." % - (value, t) - ) - except ClientSideError as e: - self.assertIsInstance(e, InvalidInput) - self.assertEqual(e.fieldname, 'a') - self.assertEqual(e.value, value) - - def test_ambiguous_to_bool(self): - amb_values = ('', 'randomstring', '2', '-32', 'not true') - for value in amb_values: - for ba in True, False: - jd = '"%s"' if ba else '{"a": "%s"}' - try: - parse(jd % value, {'a': bool}, ba) - assert False, ( - "Value '%s' should not parse correctly for %s." % - (value, bool) - ) - except ClientSideError as e: - self.assertIsInstance(e, InvalidInput) - self.assertEqual(e.fieldname, 'a') - self.assertEqual(e.value, value) - - def test_true_strings_to_bool(self): - true_values = ('true', 't', 'yes', 'y', 'on', '1') - for value in true_values: - for ba in True, False: - jd = '"%s"' if ba else '{"a": "%s"}' - i = parse(jd % value, {'a': bool}, ba) - self.assertIsInstance(i['a'], bool) - self.assertTrue(i['a']) - - def test_false_strings_to_bool(self): - false_values = ('false', 'f', 'no', 'n', 'off', '0') - for value in false_values: - for ba in True, False: - jd = '"%s"' if ba else '{"a": "%s"}' - i = parse(jd % value, {'a': bool}, ba) - self.assertIsInstance(i['a'], bool) - self.assertFalse(i['a']) - - def test_true_ints_to_bool(self): - true_values = (1, 5, -3) - for value in true_values: - for ba in True, False: - jd = '%d' if ba else '{"a": %d}' - i = parse(jd % value, {'a': bool}, ba) - self.assertIsInstance(i['a'], bool) - self.assertTrue(i['a']) - - def test_false_ints_to_bool(self): - value = 0 - for ba in True, False: - jd = '%d' if ba else '{"a": %d}' - i = parse(jd % value, {'a': bool}, ba) - self.assertIsInstance(i['a'], bool) - self.assertFalse(i['a']) - - def test_valid_simple_custom_type_fromjson(self): - value = 2 - for ba in True, False: - jd = '"%d"' if ba else '{"a": "%d"}' - i = parse(jd % value, {'a': CustomInt()}, ba) - self.assertEqual(i, {'a': 2}) - self.assertIsInstance(i['a'], int) - - def test_invalid_simple_custom_type_fromjson(self): - value = '2b' - for ba in True, False: - jd = '"%s"' if ba else '{"a": "%s"}' - try: - i = parse(jd % value, {'a': CustomInt()}, ba) - self.assertEqual(i, {'a': 2}) - except ClientSideError as e: - self.assertIsInstance(e, InvalidInput) - self.assertEqual(e.fieldname, 'a') - self.assertEqual(e.value, value) - self.assertEqual( - e.msg, - "invalid literal for int() with base 10: '%s'" % value - ) - - def test_parse_unexpected_attribute(self): - o = { - "id": "1", - "name": "test", - "other": "unknown", - "other2": "still unknown", - } - for ba in True, False: - jd = o if ba else {"o": o} - try: - parse(json.dumps(jd), {'o': Obj}, ba) - raise AssertionError("Object should not parse correcty.") - except wsme.exc.UnknownAttribute as e: - self.assertEqual(e.attributes, set(['other', 'other2'])) - - def test_parse_unexpected_nested_attribute(self): - no = { - "o": { - "id": "1", - "name": "test", - "other": "unknown", - }, - } - for ba in False, True: - jd = no if ba else {"no": no} - try: - parse(json.dumps(jd), {'no': NestedObj}, ba) - except wsme.exc.UnknownAttribute as e: - self.assertEqual(e.attributes, set(['other'])) - self.assertEqual(e.fieldname, "no.o") - - def test_nest_result(self): - self.root.protocols[0].nest_result = True - r = self.app.get('/returntypes/getint.json') - print(r) - assert json.loads(r.text) == {"result": 2} - - def test_encode_sample_value(self): - class MyType(object): - aint = int - astr = str - - register_type(MyType) - - v = MyType() - v.aint = 4 - v.astr = 's' - - r = wsme.rest.json.encode_sample_value(MyType, v, True) - print(r) - assert r[0] == ('javascript') - assert r[1] == json.dumps({'aint': 4, 'astr': 's'}, ensure_ascii=False, - indent=4, sort_keys=True) - - def test_bytes_tojson(self): - assert tojson(wsme.types.bytes, None) is None - assert tojson(wsme.types.bytes, b('ascii')) == u('ascii') - - def test_encode_sample_params(self): - r = wsme.rest.json.encode_sample_params( - [('a', int, 2)], True - ) - assert r[0] == 'javascript', r[0] - assert r[1] == '''{ - "a": 2 -}''', r[1] - - def test_encode_sample_result(self): - r = wsme.rest.json.encode_sample_result( - int, 2, True - ) - assert r[0] == 'javascript', r[0] - assert r[1] == '''2''' - - def test_PUT(self): - data = {"id": 1, "name": u("test")} - content = json.dumps(dict(data=data)) - headers = { - 'Content-Type': 'application/json', - } - res = self.app.put( - '/crud', - content, - headers=headers, - expect_errors=False) - print("Received:", res.body) - result = json.loads(res.text) - print(result) - assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") - assert result['message'] == "create" - - def test_GET(self): - headers = { - 'Accept': 'application/json', - } - res = self.app.get( - '/crud?ref.id=1', - headers=headers, - expect_errors=False) - print("Received:", res.body) - result = json.loads(res.text) - print(result) - assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") - - def test_GET_complex_accept(self): - headers = { - 'Accept': 'text/html,application/xml;q=0.9,*/*;q=0.8' - } - res = self.app.get( - '/crud?ref.id=1', - headers=headers, - expect_errors=False) - print("Received:", res.body) - result = json.loads(res.text) - print(result) - assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") - - def test_GET_complex_choose_xml(self): - headers = { - 'Accept': 'text/html,text/xml;q=0.9,*/*;q=0.8' - } - res = self.app.get( - '/crud?ref.id=1', - headers=headers, - expect_errors=False) - print("Received:", res.body) - assert res.content_type == 'text/xml' - - def test_GET_complex_accept_no_match(self): - headers = { - 'Accept': 'text/html,application/xml;q=0.9' - } - res = self.app.get( - '/crud?ref.id=1', - headers=headers, - status=406) - print("Received:", res.body) - assert res.body == b("Unacceptable Accept type: " - "text/html, application/xml;q=0.9 not in " - "['application/json', 'text/javascript', " - "'application/javascript', 'text/xml']") - - def test_GET_bad_simple_accept(self): - headers = { - 'Accept': 'text/plain', - } - res = self.app.get( - '/crud?ref.id=1', - headers=headers, - status=406) - print("Received:", res.body) - assert res.body == b("Unacceptable Accept type: text/plain not in " - "['application/json', 'text/javascript', " - "'application/javascript', 'text/xml']") - - def test_POST(self): - headers = { - 'Content-Type': 'application/json', - } - res = self.app.post( - '/crud', - json.dumps(dict(data=dict(id=1, name=u('test')))), - headers=headers, - expect_errors=False) - print("Received:", res.body) - result = json.loads(res.text) - print(result) - assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") - assert result['message'] == "update" - - def test_POST_bad_content_type(self): - headers = { - 'Content-Type': 'text/plain', - } - res = self.app.post( - '/crud', - json.dumps(dict(data=dict(id=1, name=u('test')))), - headers=headers, - status=415) - print("Received:", res.body) - assert res.body == b("Unacceptable Content-Type: text/plain not in " - "['application/json', 'text/javascript', " - "'application/javascript', 'text/xml']") - - def test_DELETE(self): - res = self.app.delete( - '/crud.json?ref.id=1', - expect_errors=False) - print("Received:", res.body) - result = json.loads(res.text) - print(result) - assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") - assert result['message'] == "delete" - - def test_extra_arguments(self): - headers = { - 'Accept': 'application/json', - } - res = self.app.get( - '/crud?ref.id=1&extraarg=foo', - headers=headers, - expect_errors=False) - print("Received:", res.body) - result = json.loads(res.text) - print(result) - assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") - assert result['message'] == "read" - - def test_unexpected_extra_arg(self): - headers = { - 'Content-Type': 'application/json', - } - data = {"id": 1, "name": "test"} - content = json.dumps({"data": data, "other": "unexpected"}) - res = self.app.put( - '/crud', - content, - headers=headers, - expect_errors=True) - self.assertEqual(res.status_int, 400) - - def test_unexpected_extra_attribute(self): - """Expect a failure if we send an unexpected object attribute.""" - headers = { - 'Content-Type': 'application/json', - } - data = {"id": 1, "name": "test", "other": "unexpected"} - content = json.dumps({"data": data}) - res = self.app.put( - '/crud', - content, - headers=headers, - expect_errors=True) - self.assertEqual(res.status_int, 400) - - def test_body_arg(self): - headers = { - 'Content-Type': 'application/json', - } - res = self.app.post( - '/crud/update_with_body?msg=hello', - json.dumps(dict(id=1, name=u('test'))), - headers=headers, - expect_errors=False) - print("Received:", res.body) - result = json.loads(res.text) - print(result) - assert result['data']['id'] == 1 - assert result['data']['name'] == u("test") - assert result['message'] == "hello" diff --git a/wsme/tests/test_restxml.py b/wsme/tests/test_restxml.py deleted file mode 100644 index b677a65..0000000 --- a/wsme/tests/test_restxml.py +++ /dev/null @@ -1,211 +0,0 @@ -import decimal -import datetime -import base64 - -from six import u, b -import six - -import wsme.tests.protocol -from wsme.utils import parse_isodatetime, parse_isodate, parse_isotime -from wsme.types import isarray, isdict, isusertype, register_type - -from wsme.rest.xml import fromxml, toxml - -try: - import xml.etree.ElementTree as et -except ImportError: - import cElementTree as et # noqa - - -def dumpxml(key, obj, datatype=None): - el = et.Element(key) - if isinstance(obj, tuple): - obj, datatype = obj - if isinstance(datatype, list): - for item in obj: - el.append(dumpxml('item', item, datatype[0])) - elif isinstance(datatype, dict): - key_type, value_type = list(datatype.items())[0] - for item in obj.items(): - node = et.SubElement(el, 'item') - node.append(dumpxml('key', item[0], key_type)) - node.append(dumpxml('value', item[1], value_type)) - elif datatype == wsme.types.binary: - el.text = base64.encodestring(obj).decode('ascii') - elif isinstance(obj, wsme.types.bytes): - el.text = obj.decode('ascii') - elif isinstance(obj, wsme.types.text): - el.text = obj - elif type(obj) in (int, float, bool, decimal.Decimal): - el.text = six.text_type(obj) - elif type(obj) in (datetime.date, datetime.time, datetime.datetime): - el.text = obj.isoformat() - elif isinstance(obj, type(None)): - el.set('nil', 'true') - elif hasattr(datatype, '_wsme_attributes'): - for attr in datatype._wsme_attributes: - name = attr.name - if name not in obj: - continue - o = obj[name] - el.append(dumpxml(name, o, attr.datatype)) - elif type(obj) == dict: - for name, value in obj.items(): - el.append(dumpxml(name, value)) - print(obj, datatype, et.tostring(el)) - return el - - -def loadxml(el, datatype): - print(el, datatype, len(el)) - if el.get('nil') == 'true': - return None - if isinstance(datatype, list): - return [loadxml(item, datatype[0]) for item in el.findall('item')] - elif isarray(datatype): - return [ - loadxml(item, datatype.item_type) for item in el.findall('item') - ] - elif isinstance(datatype, dict): - key_type, value_type = list(datatype.items())[0] - return dict(( - (loadxml(item.find('key'), key_type), - loadxml(item.find('value'), value_type)) - for item in el.findall('item') - )) - elif isdict(datatype): - return dict(( - (loadxml(item.find('key'), datatype.key_type), - loadxml(item.find('value'), datatype.value_type)) - for item in el.findall('item') - )) - elif isdict(datatype): - return dict(( - (loadxml(item.find('key'), datatype.key_type), - loadxml(item.find('value'), datatype.value_type)) - for item in el.findall('item') - )) - elif len(el): - d = {} - for attr in datatype._wsme_attributes: - name = attr.name - child = el.find(name) - print(name, attr, child) - if child is not None: - d[name] = loadxml(child, attr.datatype) - print(d) - return d - else: - if datatype == wsme.types.binary: - return base64.decodestring(el.text.encode('ascii')) - if isusertype(datatype): - datatype = datatype.basetype - if datatype == datetime.date: - return parse_isodate(el.text) - if datatype == datetime.time: - return parse_isotime(el.text) - if datatype == datetime.datetime: - return parse_isodatetime(el.text) - if datatype == wsme.types.text: - return datatype(el.text if el.text else u('')) - if datatype == bool: - return el.text.lower() != 'false' - if datatype is None: - return el.text - if datatype is wsme.types.bytes: - return el.text.encode('ascii') - return datatype(el.text) - - -class TestRestXML(wsme.tests.protocol.RestOnlyProtocolTestCase): - protocol = 'restxml' - - def call(self, fpath, _rt=None, _accept=None, _no_result_decode=False, - body=None, **kw): - if body: - el = dumpxml('body', body) - else: - el = dumpxml('parameters', kw) - content = et.tostring(el) - headers = { - 'Content-Type': 'text/xml', - } - if _accept is not None: - headers['Accept'] = _accept - res = self.app.post( - '/' + fpath, - content, - headers=headers, - expect_errors=True) - print("Received:", res.body) - - if _no_result_decode: - return res - - el = et.fromstring(res.body) - if el.tag == 'error': - raise wsme.tests.protocol.CallException( - el.find('faultcode').text, - el.find('faultstring').text, - el.find('debuginfo') is not None and - el.find('debuginfo').text or None - ) - - else: - return loadxml(et.fromstring(res.body), _rt) - - def test_encode_sample_value(self): - class MyType(object): - aint = int - atext = wsme.types.text - - register_type(MyType) - - value = MyType() - value.aint = 5 - value.atext = u('test') - - language, sample = wsme.rest.xml.encode_sample_value( - MyType, value, True) - print(language, sample) - - assert language == 'xml' - assert sample == b("""<value> - <aint>5</aint> - <atext>test</atext> -</value>""") - - def test_encode_sample_params(self): - lang, content = wsme.rest.xml.encode_sample_params( - [('a', int, 2)], True) - assert lang == 'xml', lang - assert content == b('<parameters>\n <a>2</a>\n</parameters>'), content - - def test_encode_sample_result(self): - lang, content = wsme.rest.xml.encode_sample_result(int, 2, True) - assert lang == 'xml', lang - assert content == b('<result>2</result>'), content - - def test_nil_fromxml(self): - for dt in ( - str, [int], {int: str}, bool, - datetime.date, datetime.time, datetime.datetime): - e = et.Element('value', nil='true') - assert fromxml(dt, e) is None - - def test_nil_toxml(self): - for dt in ( - wsme.types.bytes, - [int], {int: str}, bool, - datetime.date, datetime.time, datetime.datetime): - x = et.tostring(toxml(dt, 'value', None)) - assert x == b('<value nil="true" />'), x - - def test_unset_attrs(self): - class AType(object): - someattr = wsme.types.bytes - - wsme.types.register_type(AType) - - x = et.tostring(toxml(AType, 'value', AType())) - assert x == b('<value />'), x diff --git a/wsme/tests/test_root.py b/wsme/tests/test_root.py deleted file mode 100644 index 8ccb0c1..0000000 --- a/wsme/tests/test_root.py +++ /dev/null @@ -1,122 +0,0 @@ -# encoding=utf8 - -import unittest - -from wsme import WSRoot -import wsme.protocol -import wsme.rest.protocol -from wsme.root import default_prepare_response_body - -from six import b, u -from webob import Request - - -class TestRoot(unittest.TestCase): - def test_default_transaction(self): - import transaction - root = WSRoot(transaction=True) - assert root._transaction is transaction - - txn = root.begin() - txn.abort() - - def test_default_prepare_response_body(self): - default_prepare_response_body(None, [b('a')]) == b('a') - default_prepare_response_body(None, [b('a'), b('b')]) == b('a\nb') - default_prepare_response_body(None, [u('a')]) == u('a') - default_prepare_response_body(None, [u('a'), u('b')]) == u('a\nb') - - def test_protocol_selection_error(self): - class P(wsme.protocol.Protocol): - name = "test" - - def accept(self, r): - raise Exception('test') - - root = WSRoot() - root.addprotocol(P()) - - from webob import Request - req = Request.blank('/test?check=a&check=b&name=Bob') - res = root._handle_request(req) - assert res.status_int == 500 - assert res.content_type == 'text/plain' - assert (res.text == - 'Unexpected error while selecting protocol: test'), req.text - - def test_protocol_selection_accept_mismatch(self): - """Verify that we get a 406 error on wrong Accept header.""" - class P(wsme.protocol.Protocol): - name = "test" - - def accept(self, r): - return False - - root = WSRoot() - root.addprotocol(wsme.rest.protocol.RestProtocol()) - root.addprotocol(P()) - - req = Request.blank('/test?check=a&check=b&name=Bob') - req.method = 'GET' - res = root._handle_request(req) - assert res.status_int == 406 - assert res.content_type == 'text/plain' - assert res.text.startswith( - 'None of the following protocols can handle this request' - ), req.text - - def test_protocol_selection_content_type_mismatch(self): - """Verify that we get a 415 error on wrong Content-Type header.""" - class P(wsme.protocol.Protocol): - name = "test" - - def accept(self, r): - return False - - root = WSRoot() - root.addprotocol(wsme.rest.protocol.RestProtocol()) - root.addprotocol(P()) - - req = Request.blank('/test?check=a&check=b&name=Bob') - req.method = 'POST' - req.headers['Content-Type'] = "test/unsupported" - res = root._handle_request(req) - assert res.status_int == 415 - assert res.content_type == 'text/plain' - assert res.text.startswith( - 'Unacceptable Content-Type: test/unsupported not in' - ), req.text - - def test_protocol_selection_get_method(self): - class P(wsme.protocol.Protocol): - name = "test" - - def accept(self, r): - return True - - root = WSRoot() - root.addprotocol(wsme.rest.protocol.RestProtocol()) - root.addprotocol(P()) - - req = Request.blank('/test?check=a&check=b&name=Bob') - req.method = 'GET' - req.headers['Accept'] = 'test/fake' - p = root._select_protocol(req) - assert p.name == "test" - - def test_protocol_selection_post_method(self): - class P(wsme.protocol.Protocol): - name = "test" - - def accept(self, r): - return True - - root = WSRoot() - root.addprotocol(wsme.rest.protocol.RestProtocol()) - root.addprotocol(P()) - - req = Request.blank('/test?check=a&check=b&name=Bob') - req.headers['Content-Type'] = 'test/fake' - req.method = 'POST' - p = root._select_protocol(req) - assert p.name == "test" diff --git a/wsme/tests/test_spore.py b/wsme/tests/test_spore.py deleted file mode 100644 index d6509f3..0000000 --- a/wsme/tests/test_spore.py +++ /dev/null @@ -1,51 +0,0 @@ -import unittest - -try: - import simplejson as json -except ImportError: - import json - -from wsme.tests.protocol import WSTestRoot -import wsme.tests.test_restjson -import wsme.spore - - -class TestSpore(unittest.TestCase): - def test_spore(self): - spore = wsme.spore.getdesc(WSTestRoot()) - - print(spore) - - spore = json.loads(spore) - - assert len(spore['methods']) == 51, str(len(spore['methods'])) - - m = spore['methods']['argtypes_setbytesarray'] - assert m['path'] == 'argtypes/setbytesarray', m['path'] - assert m['optional_params'] == ['value'] - assert m['method'] == 'POST' - - m = spore['methods']['argtypes_setdecimal'] - assert m['path'] == 'argtypes/setdecimal' - assert m['required_params'] == ['value'] - assert m['method'] == 'GET' - - m = spore['methods']['crud_create'] - assert m['path'] == 'crud' - assert m['method'] == 'PUT' - assert m['optional_params'] == ['data'] - - m = spore['methods']['crud_read'] - assert m['path'] == 'crud' - assert m['method'] == 'GET' - assert m['required_params'] == ['ref'] - - m = spore['methods']['crud_update'] - assert m['path'] == 'crud' - assert m['method'] == 'POST' - assert m['optional_params'] == ['data'] - - m = spore['methods']['crud_delete'] - assert m['path'] == 'crud' - assert m['method'] == 'DELETE' - assert m['optional_params'] == ['ref'] diff --git a/wsme/tests/test_types.py b/wsme/tests/test_types.py deleted file mode 100644 index 4a07130..0000000 --- a/wsme/tests/test_types.py +++ /dev/null @@ -1,667 +0,0 @@ -import re -try: - import unittest2 as unittest -except ImportError: - import unittest -import six - -from wsme import exc -from wsme import types - - -def gen_class(): - d = {} - exec('''class tmp(object): pass''', d) - return d['tmp'] - - -class TestTypes(unittest.TestCase): - def setUp(self): - types.registry = types.Registry() - - def test_default_usertype(self): - class MyType(types.UserType): - basetype = str - - My = MyType() - - assert My.validate('a') == 'a' - assert My.tobasetype('a') == 'a' - assert My.frombasetype('a') == 'a' - - def test_unset(self): - u = types.Unset - - assert not u - - def test_flat_type(self): - class Flat(object): - aint = int - abytes = six.binary_type - atext = six.text_type - afloat = float - - types.register_type(Flat) - - assert len(Flat._wsme_attributes) == 4 - attrs = Flat._wsme_attributes - print(attrs) - - assert attrs[0].key == 'aint' - assert attrs[0].name == 'aint' - assert isinstance(attrs[0], types.wsattr) - assert attrs[0].datatype == int - assert attrs[0].mandatory is False - assert attrs[1].key == 'abytes' - assert attrs[1].name == 'abytes' - assert attrs[2].key == 'atext' - assert attrs[2].name == 'atext' - assert attrs[3].key == 'afloat' - assert attrs[3].name == 'afloat' - - def test_private_attr(self): - class WithPrivateAttrs(object): - _private = 12 - - types.register_type(WithPrivateAttrs) - - assert len(WithPrivateAttrs._wsme_attributes) == 0 - - def test_attribute_order(self): - class ForcedOrder(object): - _wsme_attr_order = ('a2', 'a1', 'a3') - a1 = int - a2 = int - a3 = int - - types.register_type(ForcedOrder) - - print(ForcedOrder._wsme_attributes) - assert ForcedOrder._wsme_attributes[0].key == 'a2' - assert ForcedOrder._wsme_attributes[1].key == 'a1' - assert ForcedOrder._wsme_attributes[2].key == 'a3' - - c = gen_class() - print(c) - types.register_type(c) - del c._wsme_attributes - - c.a2 = int - c.a1 = int - c.a3 = int - - types.register_type(c) - - assert c._wsme_attributes[0].key == 'a1', c._wsme_attributes[0].key - assert c._wsme_attributes[1].key == 'a2' - assert c._wsme_attributes[2].key == 'a3' - - def test_wsproperty(self): - class WithWSProp(object): - def __init__(self): - self._aint = 0 - - def get_aint(self): - return self._aint - - def set_aint(self, value): - self._aint = value - - aint = types.wsproperty(int, get_aint, set_aint, mandatory=True) - - types.register_type(WithWSProp) - - print(WithWSProp._wsme_attributes) - assert len(WithWSProp._wsme_attributes) == 1 - a = WithWSProp._wsme_attributes[0] - assert a.key == 'aint' - assert a.datatype == int - assert a.mandatory - - o = WithWSProp() - o.aint = 12 - - assert o.aint == 12 - - def test_nested(self): - class Inner(object): - aint = int - - class Outer(object): - inner = Inner - - types.register_type(Outer) - - assert hasattr(Inner, '_wsme_attributes') - assert len(Inner._wsme_attributes) == 1 - - def test_inspect_with_inheritance(self): - class Parent(object): - parent_attribute = int - - class Child(Parent): - child_attribute = int - - types.register_type(Parent) - types.register_type(Child) - - assert len(Child._wsme_attributes) == 2 - - def test_selfreftype(self): - class SelfRefType(object): - pass - - SelfRefType.parent = SelfRefType - - types.register_type(SelfRefType) - - def test_inspect_with_property(self): - class AType(object): - @property - def test(self): - return 'test' - - types.register_type(AType) - - assert len(AType._wsme_attributes) == 0 - assert AType().test == 'test' - - def test_enum(self): - aenum = types.Enum(str, 'v1', 'v2') - assert aenum.basetype is str - - class AType(object): - a = aenum - - types.register_type(AType) - - assert AType.a.datatype is aenum - - obj = AType() - obj.a = 'v1' - assert obj.a == 'v1', repr(obj.a) - - self.assertRaisesRegexp(exc.InvalidInput, - "Invalid input for field/attribute a. \ -Value: 'v3'. Value should be one of: v., v.", - setattr, - obj, - 'a', - 'v3') - - def test_attribute_validation(self): - class AType(object): - alist = [int] - aint = int - - types.register_type(AType) - - obj = AType() - - obj.alist = [1, 2, 3] - assert obj.alist == [1, 2, 3] - obj.aint = 5 - assert obj.aint == 5 - - self.assertRaises(exc.InvalidInput, setattr, obj, 'alist', 12) - self.assertRaises(exc.InvalidInput, setattr, obj, 'alist', [2, 'a']) - - def test_attribute_validation_minimum(self): - class ATypeInt(object): - attr = types.IntegerType(minimum=1, maximum=5) - - types.register_type(ATypeInt) - - obj = ATypeInt() - obj.attr = 2 - - # comparison between 'zero' value and intger minimum (1) raises a - # TypeError which must be wrapped into an InvalidInput exception - self.assertRaises(exc.InvalidInput, setattr, obj, 'attr', 'zero') - - def test_text_attribute_conversion(self): - class SType(object): - atext = types.text - abytes = types.bytes - - types.register_type(SType) - - obj = SType() - - obj.atext = six.b('somebytes') - assert obj.atext == six.u('somebytes') - assert isinstance(obj.atext, types.text) - - obj.abytes = six.u('sometext') - assert obj.abytes == six.b('sometext') - assert isinstance(obj.abytes, types.bytes) - - def test_named_attribute(self): - class ABCDType(object): - a_list = types.wsattr([int], name='a.list') - astr = str - - types.register_type(ABCDType) - - assert len(ABCDType._wsme_attributes) == 2 - attrs = ABCDType._wsme_attributes - - assert attrs[0].key == 'a_list', attrs[0].key - assert attrs[0].name == 'a.list', attrs[0].name - assert attrs[1].key == 'astr', attrs[1].key - assert attrs[1].name == 'astr', attrs[1].name - - def test_wsattr_del(self): - class MyType(object): - a = types.wsattr(int) - - types.register_type(MyType) - - value = MyType() - - value.a = 5 - assert value.a == 5 - del value.a - assert value.a is types.Unset - - def test_validate_dict(self): - assert types.validate_value({int: str}, {1: '1', 5: '5'}) - - self.assertRaises(ValueError, types.validate_value, - {int: str}, []) - - assert types.validate_value({int: str}, {'1': '1', 5: '5'}) - - self.assertRaises(ValueError, types.validate_value, - {int: str}, {1: 1, 5: '5'}) - - def test_validate_list_valid(self): - assert types.validate_value([int], [1, 2]) - assert types.validate_value([int], ['5']) - - def test_validate_list_empty(self): - assert types.validate_value([int], []) == [] - - def test_validate_list_none(self): - v = types.ArrayType(int) - assert v.validate(None) is None - - def test_validate_list_invalid_member(self): - self.assertRaises(ValueError, types.validate_value, [int], - ['not-a-number']) - - def test_validate_list_invalid_type(self): - self.assertRaises(ValueError, types.validate_value, [int], 1) - - def test_validate_float(self): - self.assertEqual(types.validate_value(float, 1), 1.0) - self.assertEqual(types.validate_value(float, '1'), 1.0) - self.assertEqual(types.validate_value(float, 1.1), 1.1) - self.assertRaises(ValueError, types.validate_value, float, []) - self.assertRaises(ValueError, types.validate_value, float, - 'not-a-float') - - def test_validate_int(self): - self.assertEqual(types.validate_value(int, 1), 1) - self.assertEqual(types.validate_value(int, '1'), 1) - self.assertEqual(types.validate_value(int, six.u('1')), 1) - self.assertRaises(ValueError, types.validate_value, int, 1.1) - - def test_validate_integer_type(self): - v = types.IntegerType(minimum=1, maximum=10) - v.validate(1) - v.validate(5) - v.validate(10) - self.assertRaises(ValueError, v.validate, 0) - self.assertRaises(ValueError, v.validate, 11) - - def test_validate_string_type(self): - v = types.StringType(min_length=1, max_length=10, - pattern='^[a-zA-Z0-9]*$') - v.validate('1') - v.validate('12345') - v.validate('1234567890') - self.assertRaises(ValueError, v.validate, '') - self.assertRaises(ValueError, v.validate, '12345678901') - - # Test a pattern validation - v.validate('a') - v.validate('A') - self.assertRaises(ValueError, v.validate, '_') - - def test_validate_string_type_precompile(self): - precompile = re.compile('^[a-zA-Z0-9]*$') - v = types.StringType(min_length=1, max_length=10, - pattern=precompile) - - # Test a pattern validation - v.validate('a') - v.validate('A') - self.assertRaises(ValueError, v.validate, '_') - - def test_validate_string_type_pattern_exception_message(self): - regex = '^[a-zA-Z0-9]*$' - v = types.StringType(pattern=regex) - try: - v.validate('_') - self.assertFail() - except ValueError as e: - self.assertIn(regex, str(e)) - - def test_validate_ipv4_address_type(self): - v = types.IPv4AddressType() - self.assertEqual(v.validate('127.0.0.1'), '127.0.0.1') - self.assertEqual(v.validate('192.168.0.1'), '192.168.0.1') - self.assertEqual(v.validate(u'8.8.1.1'), u'8.8.1.1') - self.assertRaises(ValueError, v.validate, '') - self.assertRaises(ValueError, v.validate, 'foo') - self.assertRaises(ValueError, v.validate, - '2001:0db8:bd05:01d2:288a:1fc0:0001:10ee') - self.assertRaises(ValueError, v.validate, '1.2.3') - - def test_validate_ipv6_address_type(self): - v = types.IPv6AddressType() - self.assertEqual(v.validate('0:0:0:0:0:0:0:1'), - '0:0:0:0:0:0:0:1') - self.assertEqual(v.validate(u'0:0:0:0:0:0:0:1'), u'0:0:0:0:0:0:0:1') - self.assertEqual(v.validate('2001:0db8:bd05:01d2:288a:1fc0:0001:10ee'), - '2001:0db8:bd05:01d2:288a:1fc0:0001:10ee') - self.assertRaises(ValueError, v.validate, '') - self.assertRaises(ValueError, v.validate, 'foo') - self.assertRaises(ValueError, v.validate, '192.168.0.1') - self.assertRaises(ValueError, v.validate, '0:0:0:0:0:0:1') - - def test_validate_uuid_type(self): - v = types.UuidType() - self.assertEqual(v.validate('6a0a707c-45ef-4758-b533-e55adddba8ce'), - '6a0a707c-45ef-4758-b533-e55adddba8ce') - self.assertEqual(v.validate('6a0a707c45ef4758b533e55adddba8ce'), - '6a0a707c-45ef-4758-b533-e55adddba8ce') - self.assertRaises(ValueError, v.validate, '') - self.assertRaises(ValueError, v.validate, 'foo') - self.assertRaises(ValueError, v.validate, - '6a0a707c-45ef-4758-b533-e55adddba8ce-a') - - def test_register_invalid_array(self): - self.assertRaises(ValueError, types.register_type, []) - self.assertRaises(ValueError, types.register_type, [int, str]) - self.assertRaises(AttributeError, types.register_type, [1]) - - def test_register_invalid_dict(self): - self.assertRaises(ValueError, types.register_type, {}) - self.assertRaises(ValueError, types.register_type, - {int: str, str: int}) - self.assertRaises(ValueError, types.register_type, - {types.Unset: str}) - - def test_list_attribute_no_auto_register(self): - class MyType(object): - aint = int - - assert not hasattr(MyType, '_wsme_attributes') - - self.assertRaises(TypeError, types.list_attributes, MyType) - - assert not hasattr(MyType, '_wsme_attributes') - - def test_list_of_complextypes(self): - class A(object): - bs = types.wsattr(['B']) - - class B(object): - i = int - - types.register_type(A) - types.register_type(B) - - assert A.bs.datatype.item_type is B - - def test_cross_referenced_types(self): - class A(object): - b = types.wsattr('B') - - class B(object): - a = A - - types.register_type(A) - types.register_type(B) - - assert A.b.datatype is B - - def test_base(self): - class B1(types.Base): - b2 = types.wsattr('B2') - - class B2(types.Base): - b2 = types.wsattr('B2') - - assert B1.b2.datatype is B2, repr(B1.b2.datatype) - assert B2.b2.datatype is B2 - - def test_base_init(self): - class C1(types.Base): - s = six.text_type - - c = C1(s=six.u('test')) - assert c.s == six.u('test') - - def test_array_eq(self): - ell = [types.ArrayType(str)] - assert types.ArrayType(str) in ell - - def test_array_sample(self): - s = types.ArrayType(str).sample() - assert isinstance(s, list) - assert s - assert s[0] == '' - - def test_dict_sample(self): - s = types.DictType(str, str).sample() - assert isinstance(s, dict) - assert s - assert s == {'': ''} - - def test_binary_to_base(self): - import base64 - assert types.binary.tobasetype(None) is None - expected = base64.encodestring(six.b('abcdef')) - assert types.binary.tobasetype(six.b('abcdef')) == expected - - def test_binary_from_base(self): - import base64 - assert types.binary.frombasetype(None) is None - encoded = base64.encodestring(six.b('abcdef')) - assert types.binary.frombasetype(encoded) == six.b('abcdef') - - def test_wsattr_weakref_datatype(self): - # If the datatype inside the wsattr ends up a weakref, it - # should be converted to the real type when accessed again by - # the property getter. - import weakref - a = types.wsattr(int) - a.datatype = weakref.ref(int) - assert a.datatype is int - - def test_wsattr_list_datatype(self): - # If the datatype inside the wsattr ends up a list of weakrefs - # to types, it should be converted to the real types when - # accessed again by the property getter. - import weakref - a = types.wsattr(int) - a.datatype = [weakref.ref(int)] - assert isinstance(a.datatype, list) - assert a.datatype[0] is int - - def test_file_get_content_by_reading(self): - class buffer: - def read(self): - return 'abcdef' - f = types.File(file=buffer()) - assert f.content == 'abcdef' - - def test_file_content_overrides_file(self): - class buffer: - def read(self): - return 'from-file' - f = types.File(content='from-content', file=buffer()) - assert f.content == 'from-content' - - def test_file_setting_content_discards_file(self): - class buffer: - def read(self): - return 'from-file' - f = types.File(file=buffer()) - f.content = 'from-content' - assert f.content == 'from-content' - - def test_file_field_storage(self): - class buffer: - def read(self): - return 'from-file' - - class fieldstorage: - filename = 'static.json' - file = buffer() - type = 'application/json' - f = types.File(fieldstorage=fieldstorage) - assert f.content == 'from-file' - - def test_file_field_storage_value(self): - class buffer: - def read(self): - return 'from-file' - - class fieldstorage: - filename = 'static.json' - file = None - type = 'application/json' - value = 'from-value' - f = types.File(fieldstorage=fieldstorage) - assert f.content == 'from-value' - - def test_file_property_file(self): - class buffer: - def read(self): - return 'from-file' - buf = buffer() - f = types.File(file=buf) - assert f.file is buf - - def test_file_property_content(self): - class buffer: - def read(self): - return 'from-file' - f = types.File(content=six.b('from-content')) - assert f.file.read() == six.b('from-content') - - def test_unregister(self): - class TempType(object): - pass - types.registry.register(TempType) - v = types.registry.lookup('TempType') - self.assertIs(v, TempType) - types.registry._unregister(TempType) - after = types.registry.lookup('TempType') - self.assertIs(after, None) - - def test_unregister_twice(self): - class TempType(object): - pass - types.registry.register(TempType) - v = types.registry.lookup('TempType') - self.assertIs(v, TempType) - types.registry._unregister(TempType) - # Second call should not raise an exception - types.registry._unregister(TempType) - after = types.registry.lookup('TempType') - self.assertIs(after, None) - - def test_unregister_array_type(self): - class TempType(object): - pass - t = [TempType] - types.registry.register(t) - self.assertNotEqual(types.registry.array_types, set()) - types.registry._unregister(t) - self.assertEqual(types.registry.array_types, set()) - - def test_unregister_array_type_twice(self): - class TempType(object): - pass - t = [TempType] - types.registry.register(t) - self.assertNotEqual(types.registry.array_types, set()) - types.registry._unregister(t) - # Second call should not raise an exception - types.registry._unregister(t) - self.assertEqual(types.registry.array_types, set()) - - def test_unregister_dict_type(self): - class TempType(object): - pass - t = {str: TempType} - types.registry.register(t) - self.assertNotEqual(types.registry.dict_types, set()) - types.registry._unregister(t) - self.assertEqual(types.registry.dict_types, set()) - - def test_unregister_dict_type_twice(self): - class TempType(object): - pass - t = {str: TempType} - types.registry.register(t) - self.assertNotEqual(types.registry.dict_types, set()) - types.registry._unregister(t) - # Second call should not raise an exception - types.registry._unregister(t) - self.assertEqual(types.registry.dict_types, set()) - - def test_reregister(self): - class TempType(object): - pass - types.registry.register(TempType) - v = types.registry.lookup('TempType') - self.assertIs(v, TempType) - types.registry.reregister(TempType) - after = types.registry.lookup('TempType') - self.assertIs(after, TempType) - - def test_reregister_and_add_attr(self): - class TempType(object): - pass - types.registry.register(TempType) - attrs = types.list_attributes(TempType) - self.assertEqual(attrs, []) - TempType.one = str - types.registry.reregister(TempType) - after = types.list_attributes(TempType) - self.assertNotEqual(after, []) - - def test_dynamicbase_add_attributes(self): - class TempType(types.DynamicBase): - pass - types.registry.register(TempType) - attrs = types.list_attributes(TempType) - self.assertEqual(attrs, []) - TempType.add_attributes(one=str) - after = types.list_attributes(TempType) - self.assertEqual(len(after), 1) - - def test_dynamicbase_add_attributes_second(self): - class TempType(types.DynamicBase): - pass - types.registry.register(TempType) - attrs = types.list_attributes(TempType) - self.assertEqual(attrs, []) - TempType.add_attributes(one=str) - TempType.add_attributes(two=int) - after = types.list_attributes(TempType) - self.assertEqual(len(after), 2) - - def test_non_registered_complex_type(self): - class TempType(types.Base): - __registry__ = None - - self.assertFalse(types.iscomplex(TempType)) - types.registry.register(TempType) - self.assertTrue(types.iscomplex(TempType)) diff --git a/wsme/tests/test_utils.py b/wsme/tests/test_utils.py deleted file mode 100644 index f9464c8..0000000 --- a/wsme/tests/test_utils.py +++ /dev/null @@ -1,97 +0,0 @@ -import datetime -import unittest -import pytz - -from wsme import utils - - -class TestUtils(unittest.TestCase): - def test_parse_isodate(self): - good_dates = [ - ('2008-02-01', datetime.date(2008, 2, 1)), - ('2009-01-04', datetime.date(2009, 1, 4)), - ] - ill_formatted_dates = [ - '24-12-2004' - ] - out_of_range_dates = [ - '0000-00-00', - '2012-02-30', - ] - for s, d in good_dates: - assert utils.parse_isodate(s) == d - for s in ill_formatted_dates + out_of_range_dates: - self.assertRaises(ValueError, utils.parse_isodate, s) - - def test_parse_isotime(self): - good_times = [ - ('12:03:54', datetime.time(12, 3, 54)), - ('23:59:59.000004', datetime.time(23, 59, 59, 4)), - ('01:02:03+00:00', datetime.time(1, 2, 3, 0, pytz.UTC)), - ('01:02:03+23:59', datetime.time(1, 2, 3, 0, - pytz.FixedOffset(1439))), - ('01:02:03-23:59', datetime.time(1, 2, 3, 0, - pytz.FixedOffset(-1439))), - ] - ill_formatted_times = [ - '24-12-2004' - ] - out_of_range_times = [ - '32:12:00', - '00:54:60', - '01:02:03-24:00', - '01:02:03+24:00', - ] - for s, t in good_times: - assert utils.parse_isotime(s) == t - for s in ill_formatted_times + out_of_range_times: - self.assertRaises(ValueError, utils.parse_isotime, s) - - def test_parse_isodatetime(self): - good_datetimes = [ - ('2008-02-12T12:03:54', - datetime.datetime(2008, 2, 12, 12, 3, 54)), - ('2012-05-14T23:59:59.000004', - datetime.datetime(2012, 5, 14, 23, 59, 59, 4)), - ('1856-07-10T01:02:03+00:00', - datetime.datetime(1856, 7, 10, 1, 2, 3, 0, pytz.UTC)), - ('1856-07-10T01:02:03+23:59', - datetime.datetime(1856, 7, 10, 1, 2, 3, 0, - pytz.FixedOffset(1439))), - ('1856-07-10T01:02:03-23:59', - datetime.datetime(1856, 7, 10, 1, 2, 3, 0, - pytz.FixedOffset(-1439))), - ] - ill_formatted_datetimes = [ - '24-32-2004', - '1856-07-10+33:00' - ] - out_of_range_datetimes = [ - '2008-02-12T32:12:00', - '2012-13-12T00:54:60', - ] - for s, t in good_datetimes: - assert utils.parse_isodatetime(s) == t - for s in ill_formatted_datetimes + out_of_range_datetimes: - self.assertRaises(ValueError, utils.parse_isodatetime, s) - - def test_validator_with_valid_code(self): - valid_code = 404 - self.assertTrue( - utils.is_valid_code(valid_code), - "Valid status code not detected" - ) - - def test_validator_with_invalid_int_code(self): - invalid_int_code = 648 - self.assertFalse( - utils.is_valid_code(invalid_int_code), - "Invalid status code not detected" - ) - - def test_validator_with_invalid_str_code(self): - invalid_str_code = '404' - self.assertFalse( - utils.is_valid_code(invalid_str_code), - "Invalid status code not detected" - ) |