Awesome IRC bot
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.
 
 
 

221 lines
7.2 KiB

  1. import os
  2. import pytest
  3. from pyircbot import jsonrpc
  4. from threading import Thread
  5. from random import randint
  6. from time import sleep
  7. # Sample server methods
  8. def sample(value):
  9. return value
  10. class _sample(object):
  11. def sample(self, value):
  12. return value
  13. def client(port, v=2):
  14. return jsonrpc.ServerProxy((jsonrpc.JsonRpc20 if v == 2 else jsonrpc.JsonRpc10)(),
  15. jsonrpc.TransportTcpIp(addr=("127.0.0.1", port), timeout=2.0))
  16. # Fixures for each server version provide a (server_instance, port) tuple.
  17. # Each have the method "sample", which returns the value passed
  18. # Each have a class instance registered as "obj", which the method "sample" as well
  19. @pytest.fixture
  20. def j1testserver():
  21. port = randint(40000, 60000)
  22. server = jsonrpc.Server(jsonrpc.JsonRpc10(),
  23. jsonrpc.TransportTcpIp(addr=("127.0.0.1", port)))
  24. server.register_function(sample)
  25. server.register_instance(_sample(), name="obj")
  26. Thread(target=server.serve, daemon=True).start()
  27. sleep(0.1) # Give the serve() time to set up the serversocket
  28. yield (server, port)
  29. server._Server__transport.close()
  30. @pytest.fixture
  31. def j2testserver():
  32. port = randint(40000, 60000)
  33. server = jsonrpc.Server(jsonrpc.JsonRpc20(),
  34. jsonrpc.TransportTcpIp(addr=("127.0.0.1", port)))
  35. server.register_function(sample)
  36. server.register_instance(_sample(), name="obj")
  37. Thread(target=server.serve, daemon=True).start()
  38. sleep(0.2) # Give the serve() time to set up the serversocket
  39. yield (server, port)
  40. server._Server__transport.close()
  41. # Basic functionality
  42. def test_1_basic(j1testserver):
  43. str(jsonrpc.RPCFault(-32700, "foo", "bar"))
  44. server, port = j1testserver
  45. str(client(port, v=1))
  46. ret = client(port, v=1).sample("foobar")
  47. assert ret == "foobar"
  48. def test_2_basic(j2testserver):
  49. server, port = j2testserver
  50. str(client(port))
  51. ret = client(port).sample("foobar")
  52. assert ret == "foobar"
  53. def test_1_instance(j1testserver):
  54. server, port = j1testserver
  55. ret = client(port, v=1).obj.sample("foobar")
  56. assert ret == "foobar"
  57. def test_2_instance(j2testserver):
  58. server, port = j2testserver
  59. ret = client(port).obj.sample("foobar")
  60. assert ret == "foobar"
  61. # Missing methods raise clean error
  62. def test_1_notfound(j1testserver):
  63. server, port = j1testserver
  64. with pytest.raises(jsonrpc.RPCMethodNotFound):
  65. client(port, v=1).idontexist("f")
  66. with pytest.raises(jsonrpc.RPCMethodNotFound):
  67. client(port, v=1).neither.idontexist("f")
  68. def test_2_notfound(j2testserver):
  69. server, port = j2testserver
  70. with pytest.raises(jsonrpc.RPCMethodNotFound):
  71. client(port).idontexist("f")
  72. with pytest.raises(jsonrpc.RPCMethodNotFound):
  73. client(port).neither.idontexist("f")
  74. # Underscore methods are blocked
  75. def test_1_underscore():
  76. with pytest.raises(AttributeError):
  77. client(-1)._notallowed()
  78. def test_2_underscore():
  79. with pytest.raises(AttributeError):
  80. client(-1)._notallowed()
  81. # Response parsing hardness
  82. def _test_1_protocol_parse_base(method):
  83. with pytest.raises(jsonrpc.RPCParseError): # Not json
  84. method("")
  85. with pytest.raises(jsonrpc.RPCInvalidRPC): # Not a dict
  86. method("[]")
  87. with pytest.raises(jsonrpc.RPCInvalidRPC): # Missing 'id'
  88. method("{}")
  89. with pytest.raises(jsonrpc.RPCInvalidRPC): # not 3 fields
  90. method('{"id": 0, "baz": 0}')
  91. def _test_2_protocol_parse_base(method):
  92. with pytest.raises(jsonrpc.RPCParseError): # Not json
  93. method("")
  94. with pytest.raises(jsonrpc.RPCInvalidRPC): # Not a dict
  95. method("[]")
  96. with pytest.raises(jsonrpc.RPCInvalidRPC): # missing jsonrpc
  97. method('{}')
  98. with pytest.raises(jsonrpc.RPCInvalidRPC): # jsonrpc must be str
  99. method('{"jsonrpc": 1}')
  100. with pytest.raises(jsonrpc.RPCInvalidRPC): # jsonrpc must be "2.0"
  101. method('{"jsonrpc": "2.1"}')
  102. def test_1_invalid_response():
  103. j = jsonrpc.JsonRpc10()
  104. _test_1_protocol_parse_base(j.loads_response)
  105. with pytest.raises(jsonrpc.RPCInvalidRPC): # can't have result and error
  106. j.loads_response('{"id": 0, "result": 1, "error": 0}')
  107. def test_2_invalid_response():
  108. j = jsonrpc.JsonRpc20()
  109. _test_2_protocol_parse_base(j.loads_response)
  110. with pytest.raises(jsonrpc.RPCInvalidRPC): # Missing 'id'
  111. j.loads_response('{"jsonrpc": "2.0"}')
  112. with pytest.raises(jsonrpc.RPCInvalidRPC): # not 4 fields
  113. j.loads_response('{"id": 0, "jsonrpc": "2.0", "bar": 1}')
  114. with pytest.raises(jsonrpc.RPCInvalidRPC): # can't have result and error
  115. j.loads_response('{"id": 0, "jsonrpc": "2.0", "result": 1, "error": 0}')
  116. # Request parsing hardness
  117. def test_1_invalid_request():
  118. j = jsonrpc.JsonRpc10()
  119. _test_1_protocol_parse_base(j.loads_request)
  120. with pytest.raises(jsonrpc.RPCInvalidRPC): # missing method
  121. j.loads_request('{"id": 0}')
  122. with pytest.raises(jsonrpc.RPCInvalidRPC): # method must be str
  123. j.loads_request('{"id": 0, "method": -1}')
  124. with pytest.raises(jsonrpc.RPCInvalidRPC): # params is bad type
  125. j.loads_request('{"id": 0, "method": "foo", "params": -1}')
  126. with pytest.raises(jsonrpc.RPCInvalidRPC): # wrong number of fields
  127. j.loads_request('{"ba": 0, "method": "foo", "asdf": 1, "foobar": 2}')
  128. j.loads_request('{"id": 0, "method": "foo", "params": []}')
  129. j.loads_request('{"method": "foo", "params": []}')
  130. # Request parsing hardness
  131. def test_2_invalid_request():
  132. j = jsonrpc.JsonRpc20()
  133. _test_2_protocol_parse_base(j.loads_request)
  134. with pytest.raises(jsonrpc.RPCInvalidRPC): # missing method
  135. j.loads_request('{"id": 0, "jsonrpc": "2.0"}')
  136. with pytest.raises(jsonrpc.RPCInvalidRPC): # method must be str
  137. j.loads_request('{"id": 0, "jsonrpc": "2.0", "method": 1}')
  138. with pytest.raises(jsonrpc.RPCInvalidRPC): # params is bad type
  139. j.loads_request('{"id": 0, "jsonrpc": "2.0", "method": "foo", "params": -1}')
  140. with pytest.raises(jsonrpc.RPCInvalidRPC): # wrong number of fields
  141. j.loads_request('{"id": 0, "jsonrpc": "2.0", "method": "foo", "asdf": 1, "foobar": 2}')
  142. j.loads_request('{"id": 0, "jsonrpc": "2.0", "method": "foo", "params": []}')
  143. j.loads_request('{"jsonrpc": "2.0", "method": "foo", "params": []}')
  144. def test_1_dumps_reqest():
  145. j = jsonrpc.JsonRpc20()
  146. with pytest.raises(TypeError):
  147. j.dumps_request(-1)
  148. with pytest.raises(TypeError):
  149. j.dumps_request("foo", params=-1)
  150. j.dumps_request("foo")
  151. def test_2_dumps_reqest():
  152. j = jsonrpc.JsonRpc20()
  153. with pytest.raises(TypeError):
  154. j.dumps_request(-1)
  155. with pytest.raises(TypeError):
  156. j.dumps_request("foo", params=-1)
  157. j.dumps_request("foo", params=[])
  158. j.dumps_request("foo")
  159. # Misc stuff
  160. def test_logging(tmpdir):
  161. msg = "test log message"
  162. jsonrpc.log_dummy(msg)
  163. jsonrpc.log_stdout(msg)
  164. logpath = os.path.join(tmpdir, "test.log")
  165. logger = jsonrpc.log_file(logpath)
  166. logger(msg)
  167. assert os.path.exists(logpath)
  168. logpath = os.path.join(tmpdir, "test2.log")
  169. logger2 = jsonrpc.log_filedate(os.path.join(tmpdir, "test2.log"))
  170. logger2(msg)
  171. assert os.path.exists(logpath)