PageRenderTime 38ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/lib/python/indra/ipc/siesta_test.py

https://bitbucket.org/lindenlab/viewer-beta/
Python | 235 lines | 205 code | 9 blank | 21 comment | 2 complexity | d32ae4c94f2f78f207bc1d3b4aceabdd MD5 | raw file
Possible License(s): LGPL-2.1
  1. #!/usr/bin/python
  2. ## $LicenseInfo:firstyear=2011&license=viewerlgpl$
  3. ## Second Life Viewer Source Code
  4. ## Copyright (C) 2011, Linden Research, Inc.
  5. ##
  6. ## This library is free software; you can redistribute it and/or
  7. ## modify it under the terms of the GNU Lesser General Public
  8. ## License as published by the Free Software Foundation;
  9. ## version 2.1 of the License only.
  10. ##
  11. ## This library is distributed in the hope that it will be useful,
  12. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ## Lesser General Public License for more details.
  15. ##
  16. ## You should have received a copy of the GNU Lesser General Public
  17. ## License along with this library; if not, write to the Free Software
  18. ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. ##
  20. ## Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  21. ## $/LicenseInfo$
  22. from indra.base import llsd, lluuid
  23. from indra.ipc import siesta
  24. import datetime, math, unittest
  25. from webob import exc
  26. class ClassApp(object):
  27. def handle_get(self, req):
  28. pass
  29. def handle_post(self, req):
  30. return req.llsd
  31. def callable_app(req):
  32. if req.method == 'UNDERPANTS':
  33. raise exc.HTTPMethodNotAllowed()
  34. elif req.method == 'GET':
  35. return None
  36. return req.llsd
  37. class TestBase:
  38. def test_basic_get(self):
  39. req = siesta.Request.blank('/')
  40. self.assertEquals(req.get_response(self.server).body,
  41. llsd.format_xml(None))
  42. def test_bad_method(self):
  43. req = siesta.Request.blank('/')
  44. req.environ['REQUEST_METHOD'] = 'UNDERPANTS'
  45. self.assertEquals(req.get_response(self.server).status_int,
  46. exc.HTTPMethodNotAllowed.code)
  47. json_safe = {
  48. 'none': None,
  49. 'bool_true': True,
  50. 'bool_false': False,
  51. 'int_zero': 0,
  52. 'int_max': 2147483647,
  53. 'int_min': -2147483648,
  54. 'long_zero': 0,
  55. 'long_max': 2147483647L,
  56. 'long_min': -2147483648L,
  57. 'float_zero': 0,
  58. 'float': math.pi,
  59. 'float_huge': 3.14159265358979323846e299,
  60. 'str_empty': '',
  61. 'str': 'foo',
  62. u'unic\u1e51de_empty': u'',
  63. u'unic\u1e51de': u'\u1e4exx\u10480',
  64. }
  65. json_safe['array'] = json_safe.values()
  66. json_safe['tuple'] = tuple(json_safe.values())
  67. json_safe['dict'] = json_safe.copy()
  68. json_unsafe = {
  69. 'uuid_empty': lluuid.UUID(),
  70. 'uuid_full': lluuid.UUID('dc61ab0530200d7554d23510559102c1a98aab1b'),
  71. 'binary_empty': llsd.binary(),
  72. 'binary': llsd.binary('f\0\xff'),
  73. 'uri_empty': llsd.uri(),
  74. 'uri': llsd.uri('http://www.secondlife.com/'),
  75. 'datetime_empty': datetime.datetime(1970,1,1),
  76. 'datetime': datetime.datetime(1999,9,9,9,9,9),
  77. }
  78. json_unsafe.update(json_safe)
  79. json_unsafe['array'] = json_unsafe.values()
  80. json_unsafe['tuple'] = tuple(json_unsafe.values())
  81. json_unsafe['dict'] = json_unsafe.copy()
  82. json_unsafe['iter'] = iter(json_unsafe.values())
  83. def _test_client_content_type_good(self, content_type, ll):
  84. def run(ll):
  85. req = siesta.Request.blank('/')
  86. req.environ['REQUEST_METHOD'] = 'POST'
  87. req.content_type = content_type
  88. req.llsd = ll
  89. req.accept = content_type
  90. resp = req.get_response(self.server)
  91. self.assertEquals(resp.status_int, 200)
  92. return req, resp
  93. if False and isinstance(ll, dict):
  94. def fixup(v):
  95. if isinstance(v, float):
  96. return '%.5f' % v
  97. if isinstance(v, long):
  98. return int(v)
  99. if isinstance(v, (llsd.binary, llsd.uri)):
  100. return v
  101. if isinstance(v, (tuple, list)):
  102. return [fixup(i) for i in v]
  103. if isinstance(v, dict):
  104. return dict([(k, fixup(i)) for k, i in v.iteritems()])
  105. return v
  106. for k, v in ll.iteritems():
  107. l = [k, v]
  108. req, resp = run(l)
  109. self.assertEquals(fixup(resp.llsd), fixup(l))
  110. run(ll)
  111. def test_client_content_type_json_good(self):
  112. self._test_client_content_type_good('application/json', self.json_safe)
  113. def test_client_content_type_llsd_xml_good(self):
  114. self._test_client_content_type_good('application/llsd+xml',
  115. self.json_unsafe)
  116. def test_client_content_type_llsd_notation_good(self):
  117. self._test_client_content_type_good('application/llsd+notation',
  118. self.json_unsafe)
  119. def test_client_content_type_llsd_binary_good(self):
  120. self._test_client_content_type_good('application/llsd+binary',
  121. self.json_unsafe)
  122. def test_client_content_type_xml_good(self):
  123. self._test_client_content_type_good('application/xml',
  124. self.json_unsafe)
  125. def _test_client_content_type_bad(self, content_type):
  126. req = siesta.Request.blank('/')
  127. req.environ['REQUEST_METHOD'] = 'POST'
  128. req.body = '\0invalid nonsense under all encodings'
  129. req.content_type = content_type
  130. self.assertEquals(req.get_response(self.server).status_int,
  131. exc.HTTPBadRequest.code)
  132. def test_client_content_type_json_bad(self):
  133. self._test_client_content_type_bad('application/json')
  134. def test_client_content_type_llsd_xml_bad(self):
  135. self._test_client_content_type_bad('application/llsd+xml')
  136. def test_client_content_type_llsd_notation_bad(self):
  137. self._test_client_content_type_bad('application/llsd+notation')
  138. def test_client_content_type_llsd_binary_bad(self):
  139. self._test_client_content_type_bad('application/llsd+binary')
  140. def test_client_content_type_xml_bad(self):
  141. self._test_client_content_type_bad('application/xml')
  142. def test_client_content_type_bad(self):
  143. req = siesta.Request.blank('/')
  144. req.environ['REQUEST_METHOD'] = 'POST'
  145. req.body = 'XXX'
  146. req.content_type = 'application/nonsense'
  147. self.assertEquals(req.get_response(self.server).status_int,
  148. exc.HTTPUnsupportedMediaType.code)
  149. def test_request_default_content_type(self):
  150. req = siesta.Request.blank('/')
  151. self.assertEquals(req.content_type, req.default_content_type)
  152. def test_request_default_accept(self):
  153. req = siesta.Request.blank('/')
  154. from webob import acceptparse
  155. self.assertEquals(str(req.accept).replace(' ', ''),
  156. req.default_accept.replace(' ', ''))
  157. def test_request_llsd_auto_body(self):
  158. req = siesta.Request.blank('/')
  159. req.llsd = {'a': 2}
  160. self.assertEquals(req.body, '<?xml version="1.0" ?><llsd><map>'
  161. '<key>a</key><integer>2</integer></map></llsd>')
  162. def test_request_llsd_mod_body_changes_llsd(self):
  163. req = siesta.Request.blank('/')
  164. req.llsd = {'a': 2}
  165. req.body = '<?xml version="1.0" ?><llsd><integer>1337</integer></llsd>'
  166. self.assertEquals(req.llsd, 1337)
  167. def test_request_bad_llsd_fails(self):
  168. def crashme(ctype):
  169. def boom():
  170. class foo(object): pass
  171. req = siesta.Request.blank('/')
  172. req.content_type = ctype
  173. req.llsd = foo()
  174. for mime_type in siesta.llsd_parsers:
  175. self.assertRaises(TypeError, crashme(mime_type))
  176. class ClassServer(TestBase, unittest.TestCase):
  177. def __init__(self, *args, **kwargs):
  178. unittest.TestCase.__init__(self, *args, **kwargs)
  179. self.server = siesta.llsd_class(ClassApp)
  180. class CallableServer(TestBase, unittest.TestCase):
  181. def __init__(self, *args, **kwargs):
  182. unittest.TestCase.__init__(self, *args, **kwargs)
  183. self.server = siesta.llsd_callable(callable_app)
  184. class RouterServer(unittest.TestCase):
  185. def test_router(self):
  186. def foo(req, quux):
  187. print quux
  188. r = siesta.Router()
  189. r.add('/foo/{quux:int}', siesta.llsd_callable(foo), methods=['GET'])
  190. req = siesta.Request.blank('/foo/33')
  191. req.get_response(r)
  192. req = siesta.Request.blank('/foo/bar')
  193. self.assertEquals(req.get_response(r).status_int,
  194. exc.HTTPNotFound.code)
  195. if __name__ == '__main__':
  196. unittest.main()