Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.7 KiB

5 years ago
  1. """Tests for elpy.rpc."""
  2. import json
  3. import unittest
  4. import sys
  5. from elpy import rpc
  6. from elpy.tests.compat import StringIO
  7. class TestFault(unittest.TestCase):
  8. def test_should_have_code_and_data(self):
  9. fault = rpc.Fault("Hello", code=250, data="Fnord")
  10. self.assertEqual(str(fault), "Hello")
  11. self.assertEqual(fault.code, 250)
  12. self.assertEqual(fault.data, "Fnord")
  13. def test_should_have_defaults_for_code_and_data(self):
  14. fault = rpc.Fault("Hello")
  15. self.assertEqual(str(fault), "Hello")
  16. self.assertEqual(fault.code, 500)
  17. self.assertIsNone(fault.data)
  18. class TestJSONRPCServer(unittest.TestCase):
  19. def setUp(self):
  20. self.stdin = StringIO()
  21. self.stdout = StringIO()
  22. self.rpc = rpc.JSONRPCServer(self.stdin, self.stdout)
  23. def write(self, s):
  24. self.stdin.seek(0)
  25. self.stdin.truncate()
  26. self.stdout.seek(0)
  27. self.stdout.truncate()
  28. self.stdin.write(s)
  29. self.stdin.seek(0)
  30. def read(self):
  31. value = self.stdout.getvalue()
  32. self.stdin.seek(0)
  33. self.stdin.truncate()
  34. self.stdout.seek(0)
  35. self.stdout.truncate()
  36. return value
  37. class TestInit(TestJSONRPCServer):
  38. def test_should_use_arguments(self):
  39. self.assertEqual(self.rpc.stdin, self.stdin)
  40. self.assertEqual(self.rpc.stdout, self.stdout)
  41. def test_should_default_to_sys(self):
  42. testrpc = rpc.JSONRPCServer()
  43. self.assertEqual(sys.stdin, testrpc.stdin)
  44. self.assertEqual(sys.stdout, testrpc.stdout)
  45. class TestReadJson(TestJSONRPCServer):
  46. def test_should_read_json(self):
  47. objlist = [{'foo': 'bar'},
  48. {'baz': 'qux', 'fnord': 'argl\nbargl'},
  49. "beep\r\nbeep\r\nbeep"]
  50. self.write("".join([(json.dumps(obj) + "\n")
  51. for obj in objlist]))
  52. for obj in objlist:
  53. self.assertEqual(self.rpc.read_json(),
  54. obj)
  55. def test_should_raise_eof_on_eof(self):
  56. self.assertRaises(EOFError, self.rpc.read_json)
  57. def test_should_fail_on_malformed_json(self):
  58. self.write("malformed json\n")
  59. self.assertRaises(ValueError,
  60. self.rpc.read_json)
  61. class TestWriteJson(TestJSONRPCServer):
  62. def test_should_write_json_line(self):
  63. objlist = [{'foo': 'bar'},
  64. {'baz': 'qux', 'fnord': 'argl\nbargl'},
  65. ]
  66. for obj in objlist:
  67. self.rpc.write_json(**obj)
  68. self.assertEqual(json.loads(self.read()),
  69. obj)
  70. class TestHandleRequest(TestJSONRPCServer):
  71. def test_should_fail_if_json_does_not_contain_a_method(self):
  72. self.write(json.dumps(dict(params=[],
  73. id=23)))
  74. self.assertRaises(ValueError,
  75. self.rpc.handle_request)
  76. def test_should_call_right_method(self):
  77. self.write(json.dumps(dict(method='foo',
  78. params=[1, 2, 3],
  79. id=23)))
  80. self.rpc.rpc_foo = lambda *params: params
  81. self.rpc.handle_request()
  82. self.assertEqual(json.loads(self.read()),
  83. dict(id=23,
  84. result=[1, 2, 3]))
  85. def test_should_pass_defaults_for_missing_parameters(self):
  86. def test_method(*params):
  87. self.args = params
  88. self.write(json.dumps(dict(method='foo')))
  89. self.rpc.rpc_foo = test_method
  90. self.rpc.handle_request()
  91. self.assertEqual(self.args, ())
  92. self.assertEqual(self.read(), "")
  93. def test_should_return_error_for_missing_method(self):
  94. self.write(json.dumps(dict(method='foo',
  95. id=23)))
  96. self.rpc.handle_request()
  97. result = json.loads(self.read())
  98. self.assertEqual(result["id"], 23)
  99. self.assertEqual(result["error"]["message"],
  100. "Unknown method foo")
  101. def test_should_return_error_for_exception_in_method(self):
  102. def test_method():
  103. raise ValueError("An error was raised")
  104. self.write(json.dumps(dict(method='foo',
  105. id=23)))
  106. self.rpc.rpc_foo = test_method
  107. self.rpc.handle_request()
  108. result = json.loads(self.read())
  109. self.assertEqual(result["id"], 23)
  110. self.assertEqual(result["error"]["message"], "An error was raised")
  111. self.assertIn("traceback", result["error"]["data"])
  112. def test_should_not_include_traceback_for_faults(self):
  113. def test_method():
  114. raise rpc.Fault("This is a fault")
  115. self.write(json.dumps(dict(method="foo",
  116. id=23)))
  117. self.rpc.rpc_foo = test_method
  118. self.rpc.handle_request()
  119. result = json.loads(self.read())
  120. self.assertEqual(result["id"], 23)
  121. self.assertEqual(result["error"]["message"], "This is a fault")
  122. self.assertNotIn("traceback", result["error"])
  123. def test_should_add_data_for_faults(self):
  124. def test_method():
  125. raise rpc.Fault("St. Andreas' Fault",
  126. code=12345, data="Yippieh")
  127. self.write(json.dumps(dict(method="foo", id=23)))
  128. self.rpc.rpc_foo = test_method
  129. self.rpc.handle_request()
  130. result = json.loads(self.read())
  131. self.assertEqual(result["error"]["data"], "Yippieh")
  132. def test_should_call_handle_for_unknown_method(self):
  133. def test_handle(method_name, args):
  134. return "It works"
  135. self.write(json.dumps(dict(method="doesnotexist",
  136. id=23)))
  137. self.rpc.handle = test_handle
  138. self.rpc.handle_request()
  139. self.assertEqual(json.loads(self.read()),
  140. dict(id=23,
  141. result="It works"))
  142. class TestServeForever(TestJSONRPCServer):
  143. def handle_request(self):
  144. self.hr_called += 1
  145. if self.hr_called > 10:
  146. raise self.error()
  147. def setUp(self):
  148. super(TestServeForever, self).setUp()
  149. self.hr_called = 0
  150. self.error = KeyboardInterrupt
  151. self.rpc.handle_request = self.handle_request
  152. def test_should_call_handle_request_repeatedly(self):
  153. self.rpc.serve_forever()
  154. self.assertEqual(self.hr_called, 11)
  155. def test_should_return_on_some_errors(self):
  156. self.error = KeyboardInterrupt
  157. self.rpc.serve_forever()
  158. self.error = EOFError
  159. self.rpc.serve_forever()
  160. self.error = SystemExit
  161. self.rpc.serve_forever()
  162. def test_should_fail_on_most_errors(self):
  163. self.error = RuntimeError
  164. self.assertRaises(RuntimeError,
  165. self.rpc.serve_forever)