build: Initialize Python virtual environment and install project dependencies.
Some checks failed
WLED CI / wled_build (push) Has been cancelled
Some checks failed
WLED CI / wled_build (push) Has been cancelled
This commit is contained in:
407
.venv/lib/python3.11/site-packages/ajsonrpc/tests/test_core.py
Normal file
407
.venv/lib/python3.11/site-packages/ajsonrpc/tests/test_core.py
Normal file
@@ -0,0 +1,407 @@
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from ..core import (JSONRPC20BatchRequest, JSONRPC20BatchResponse,
|
||||
JSONRPC20Error, JSONRPC20InternalError,
|
||||
JSONRPC20InvalidParams, JSONRPC20InvalidRequest,
|
||||
JSONRPC20MethodNotFound, JSONRPC20ParseError,
|
||||
JSONRPC20Request, JSONRPC20RequestIdWarning,
|
||||
JSONRPC20Response, JSONRPC20ServerError)
|
||||
|
||||
|
||||
class TestJSONRPC20Request(unittest.TestCase):
|
||||
|
||||
"""Test JSONRPC20Request.
|
||||
|
||||
On creation and after modification the request object has to be valid. As
|
||||
these scenarios are almost identical, test both in test cases.
|
||||
|
||||
"""
|
||||
|
||||
#############################################
|
||||
# "method" tests
|
||||
#############################################
|
||||
|
||||
def test_method_validation_correct(self):
|
||||
r = JSONRPC20Request(method="valid", id=0)
|
||||
self.assertEqual(r.method, "valid")
|
||||
r.method = "also_valid"
|
||||
self.assertEqual(r.method, "also_valid")
|
||||
|
||||
def test_method_validation_not_str(self):
|
||||
r = JSONRPC20Request(method="valid", id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Request(method=[], id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
r.method = []
|
||||
|
||||
# invalid setters should not modify the object
|
||||
self.assertEqual(r.method, "valid")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Request(method={}, id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
r.method = {}
|
||||
|
||||
def test_method_validation_invalid_rpc_prefix(self):
|
||||
""" Test method SHOULD NOT starts with rpc."""
|
||||
r = JSONRPC20Request(method="valid", id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Request(method="rpc.", id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
r.method = "rpc."
|
||||
|
||||
# invalid setters should not modify the object
|
||||
self.assertEqual(r.method, "valid")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Request(method="rpc.test", id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
r.method = "rpc.test"
|
||||
|
||||
JSONRPC20Request(method="rpcvalid", id=0)
|
||||
JSONRPC20Request(method="rpc", id=0)
|
||||
|
||||
#############################################
|
||||
# "params" tests
|
||||
#############################################
|
||||
|
||||
def test_params_validation_none(self):
|
||||
r1 = JSONRPC20Request("null_params", params=None, id=1)
|
||||
self.assertFalse("params" in r1.body)
|
||||
|
||||
# Remove params
|
||||
r2 = JSONRPC20Request("null_params", params=[], id=2)
|
||||
self.assertTrue("params" in r2.body)
|
||||
del r2.params
|
||||
self.assertFalse("params" in r2.body)
|
||||
|
||||
def test_params_validation_list(self):
|
||||
r = JSONRPC20Request("list", params=[], id=0)
|
||||
self.assertEqual(r.params, [])
|
||||
r.params = [0, 1]
|
||||
self.assertEqual(r.params, [0, 1])
|
||||
|
||||
def test_params_validation_tuple(self):
|
||||
r = JSONRPC20Request("tuple", params=(), id=0)
|
||||
self.assertEqual(r.params, ()) # keep the same iterable
|
||||
r.params = (0, 1)
|
||||
self.assertEqual(r.params, (0, 1))
|
||||
|
||||
def test_params_validation_iterable(self):
|
||||
r1 = JSONRPC20Request("string_params", params="string", id=1)
|
||||
self.assertEqual(r1.params, "string")
|
||||
r1.params = "another string"
|
||||
self.assertEqual(r1.params, "another string")
|
||||
|
||||
r2 = JSONRPC20Request("range_params", params=range(1), id=2)
|
||||
self.assertEqual(r2.params, range(1))
|
||||
r2.params = range(2)
|
||||
self.assertEqual(r2.params, range(2))
|
||||
|
||||
def test_params_validation_dict(self):
|
||||
r1 = JSONRPC20Request("dict_params", params={}, id=1)
|
||||
self.assertEqual(r1.params, {})
|
||||
r1.params = {"a": 0}
|
||||
self.assertEqual(r1.params, {"a": 0})
|
||||
|
||||
r2 = JSONRPC20Request("dict_params", params={"a": 0}, id=2)
|
||||
self.assertEqual(r2.params, {"a": 0})
|
||||
r2.params = {"a": {}}
|
||||
self.assertEqual(r2.params, {"a": {}})
|
||||
|
||||
def test_params_validation_invalid(self):
|
||||
r = JSONRPC20Request("list", params=[], id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Request("invalid_params", params=0, id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
r.params = 0
|
||||
|
||||
self.assertEqual(r.params, [])
|
||||
|
||||
#############################################
|
||||
# "id" tests
|
||||
#############################################
|
||||
|
||||
def test_id_validation_valid(self):
|
||||
r1 = JSONRPC20Request("string_id", id="id")
|
||||
self.assertEqual(r1.id, "id")
|
||||
r1.id = "another_id"
|
||||
self.assertEqual(r1.id, "another_id")
|
||||
|
||||
r2 = JSONRPC20Request("int_id", id=0)
|
||||
self.assertEqual(r2.id, 0)
|
||||
r2.id = 1
|
||||
self.assertEqual(r2.id, 1)
|
||||
|
||||
# Null ids are possible but discouraged. Omit id for notifications.
|
||||
with warnings.catch_warnings(record=True) as _warnings:
|
||||
warnings.simplefilter("always")
|
||||
JSONRPC20Request("null_id", id=None)
|
||||
assert len(_warnings) == 1
|
||||
assert issubclass(_warnings[-1].category, JSONRPC20RequestIdWarning)
|
||||
assert "Null as a value" in str(_warnings[-1].message)
|
||||
|
||||
# Float ids are possible but discouraged
|
||||
with warnings.catch_warnings(record=True) as _warnings:
|
||||
warnings.simplefilter("always")
|
||||
JSONRPC20Request("float_id", id=0.1)
|
||||
|
||||
assert len(_warnings) == 1
|
||||
assert issubclass(_warnings[-1].category, JSONRPC20RequestIdWarning)
|
||||
assert "Fractional parts" in str(_warnings[-1].message)
|
||||
|
||||
|
||||
def test_id_validation_invalid(self):
|
||||
r = JSONRPC20Request("valid_id", id=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Request("list_id", id=[])
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
r.id = []
|
||||
|
||||
self.assertEqual(r.id, 0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Request("dict_id", id={})
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
r.id = {}
|
||||
|
||||
#############################################
|
||||
# Notification tests
|
||||
#############################################
|
||||
|
||||
def test_notification_init(self):
|
||||
r = JSONRPC20Request("notification", is_notification=True)
|
||||
self.assertTrue(r.is_notification)
|
||||
with self.assertRaises(KeyError):
|
||||
r.id
|
||||
|
||||
def test_notification_conversion(self):
|
||||
r = JSONRPC20Request("notification", id=0)
|
||||
self.assertFalse(r.is_notification)
|
||||
del r.id
|
||||
self.assertTrue(r.is_notification)
|
||||
|
||||
#############################################
|
||||
# Auxiliary methods tests
|
||||
#############################################
|
||||
|
||||
def test_request_args(self):
|
||||
self.assertEqual(JSONRPC20Request("add", id=0).args, [])
|
||||
self.assertEqual(JSONRPC20Request("add", [], id=0).args, [])
|
||||
self.assertEqual(JSONRPC20Request("add", "str", id=0).args, ["s", "t", "r"])
|
||||
self.assertEqual(JSONRPC20Request("add", {"a": 1}, id=0).args, [])
|
||||
self.assertEqual(JSONRPC20Request("add", [1, 2], id=0).args, [1, 2])
|
||||
|
||||
def test_request_kwargs(self):
|
||||
self.assertEqual(JSONRPC20Request("add", id=0).kwargs, {})
|
||||
self.assertEqual(JSONRPC20Request("add", [1, 2], id=0).kwargs, {})
|
||||
self.assertEqual(JSONRPC20Request("add", {}, id=0).kwargs, {})
|
||||
self.assertEqual(JSONRPC20Request("add", {"a": 1}, id=0).kwargs, {"a": 1})
|
||||
|
||||
#############################################
|
||||
# body methods tests
|
||||
#############################################
|
||||
def test_body_validation(self):
|
||||
r = JSONRPC20Request(method="valid", id=0)
|
||||
self.assertEqual(
|
||||
r.body,
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "valid",
|
||||
"id": 0,
|
||||
}
|
||||
)
|
||||
r.body = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "new",
|
||||
}
|
||||
self.assertEqual(r.id, 1)
|
||||
self.assertEqual(r.method, "new")
|
||||
|
||||
# body has to have "jsonrpc" in it
|
||||
with self.assertRaises(ValueError):
|
||||
r.body = {"id": 1, "method": "new"}
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
r.body = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": [],
|
||||
"method": 0,
|
||||
"params": 0,
|
||||
}
|
||||
|
||||
self.assertEqual(r.id, 1)
|
||||
self.assertEqual(r.method, "new")
|
||||
|
||||
|
||||
class TestJSONRPC20BatchRequest(unittest.TestCase):
|
||||
def test_init(self):
|
||||
br = JSONRPC20BatchRequest()
|
||||
self.assertEqual(len(br), 0)
|
||||
|
||||
br.append(JSONRPC20Request("first", id=1))
|
||||
br.extend([JSONRPC20Request("second", id=2)])
|
||||
self.assertEqual(len(br), 2)
|
||||
self.assertEqual(br[-1].method, "second")
|
||||
|
||||
|
||||
class TestJSONRPC20Error(unittest.TestCase):
|
||||
|
||||
"""Test JSONRPC20Error.
|
||||
|
||||
On creation and after modification the request object has to be valid. As
|
||||
these scenarios are almost identical, test both in test cases.
|
||||
|
||||
"""
|
||||
|
||||
#############################################
|
||||
# "code" tests
|
||||
#############################################
|
||||
|
||||
def test_code_validation_valid_numeric(self):
|
||||
e = JSONRPC20Error(code=0, message="error")
|
||||
self.assertEqual(e.code, 0)
|
||||
# Allow numeric codes. Though, prefer using integers
|
||||
e.code = 1
|
||||
self.assertEqual(e.code, 1)
|
||||
|
||||
def test_code_validation_not_number(self):
|
||||
e = JSONRPC20Error(code=0, message="error")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Error(code="0", message="error")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
e.code = "0"
|
||||
|
||||
#############################################
|
||||
# "message" tests
|
||||
#############################################
|
||||
|
||||
def test_message_validation_valid_str(self):
|
||||
e = JSONRPC20Error(code=0, message="error")
|
||||
self.assertEqual(e.message, "error")
|
||||
e.message = "specific error"
|
||||
self.assertEqual(e.message, "specific error")
|
||||
|
||||
def test_message_validation_not_str(self):
|
||||
e = JSONRPC20Error(code=0, message="error")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Error(code=0, message=0)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
e.message = 0
|
||||
|
||||
#############################################
|
||||
# "data" tests
|
||||
#############################################
|
||||
def test_data_validation_valid(self):
|
||||
e = JSONRPC20Error(code=0, message="error", data=0)
|
||||
self.assertEqual(e.data, 0)
|
||||
e.data = {"timestamp": 0}
|
||||
self.assertEqual(e.data, {"timestamp": 0})
|
||||
|
||||
def test_could_not_change_code_message_predefined_errors(self):
|
||||
errors = [
|
||||
JSONRPC20ParseError(),
|
||||
JSONRPC20InvalidRequest(),
|
||||
JSONRPC20MethodNotFound(),
|
||||
JSONRPC20InvalidParams(),
|
||||
JSONRPC20InternalError(),
|
||||
JSONRPC20ServerError(),
|
||||
]
|
||||
|
||||
for error in errors:
|
||||
with self.assertRaises(NotImplementedError):
|
||||
error.code = 0
|
||||
|
||||
with self.assertRaises(NotImplementedError):
|
||||
error.message = ""
|
||||
|
||||
|
||||
class TestJSONRPC20Response(unittest.TestCase):
|
||||
def test_valid_result(self):
|
||||
response = JSONRPC20Response(result="valid")
|
||||
self.assertEqual(response.result, "valid")
|
||||
self.assertIsNone(response.error)
|
||||
self.assertEqual(
|
||||
response.body,
|
||||
{"jsonrpc": "2.0", "id": None, "result": "valid"}
|
||||
)
|
||||
|
||||
def test_valid_error(self):
|
||||
error = JSONRPC20MethodNotFound()
|
||||
response = JSONRPC20Response(error=error)
|
||||
self.assertIsNone(response.result)
|
||||
self.assertEqual(response.error, error)
|
||||
self.assertEqual(
|
||||
response.body,
|
||||
{"jsonrpc": "2.0", "id": None, "error": error.body}
|
||||
)
|
||||
|
||||
def test_set_valid_body(self):
|
||||
response = JSONRPC20Response(result="")
|
||||
response.body = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": None,
|
||||
"error": {
|
||||
"code": 0,
|
||||
"message": "",
|
||||
}
|
||||
}
|
||||
self.assertIsInstance(response.error, JSONRPC20Error)
|
||||
|
||||
def test_set_body_result_and_error(self):
|
||||
response = JSONRPC20Response(result="")
|
||||
with self.assertRaises(ValueError):
|
||||
response.body = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": None,
|
||||
"result": "",
|
||||
"error": {
|
||||
"code": 0,
|
||||
"message": "",
|
||||
}
|
||||
}
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
JSONRPC20Response(
|
||||
result="",
|
||||
error=JSONRPC20Error(code=0, message="")
|
||||
)
|
||||
|
||||
@unittest.skip("TODO: Implement later")
|
||||
def test_set_body_error_correct_error_class(self):
|
||||
"""Return error class matching pre-defined error codes."""
|
||||
response = JSONRPC20Response(result="")
|
||||
response.body = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": None,
|
||||
"error": JSONRPC20MethodNotFound().body,
|
||||
}
|
||||
self.assertIsInstance(response.error, JSONRPC20MethodNotFound)
|
||||
|
||||
|
||||
class TestJSONRPC20BatchResponse(unittest.TestCase):
|
||||
def test_init(self):
|
||||
batch = JSONRPC20BatchResponse()
|
||||
self.assertEqual(len(batch), 0)
|
||||
|
||||
batch.append(JSONRPC20Response(result="first", id=1))
|
||||
batch.extend([JSONRPC20Response(result="second", id=2)])
|
||||
self.assertEqual(len(batch), 2)
|
||||
self.assertEqual(batch[-1].result, "second")
|
||||
@@ -0,0 +1,122 @@
|
||||
import unittest
|
||||
from ..dispatcher import Dispatcher
|
||||
|
||||
|
||||
class Math:
|
||||
@staticmethod
|
||||
def sum(a, b):
|
||||
return a + b
|
||||
|
||||
@classmethod
|
||||
def diff(cls, a, b):
|
||||
return a - b
|
||||
|
||||
def mul(self, a, b):
|
||||
return a * b
|
||||
|
||||
|
||||
class TestDispatcher(unittest.TestCase):
|
||||
def test_empty(self):
|
||||
self.assertEqual(len(Dispatcher()), 0)
|
||||
|
||||
def test_add_function(self):
|
||||
d = Dispatcher()
|
||||
|
||||
@d.add_function
|
||||
def one():
|
||||
return 1
|
||||
|
||||
def two():
|
||||
return 2
|
||||
|
||||
d.add_function(two)
|
||||
d.add_function(two, name="two_alias")
|
||||
|
||||
self.assertIn("one", d)
|
||||
self.assertEqual(d["one"](), 1)
|
||||
self.assertIsNotNone(one) # do not remove function from the scope
|
||||
self.assertIn("two", d)
|
||||
self.assertIn("two_alias", d)
|
||||
|
||||
def test_class(self):
|
||||
d1 = Dispatcher()
|
||||
d1.add_class(Math)
|
||||
self.assertIn("math.sum", d1)
|
||||
self.assertIn("math.diff", d1)
|
||||
self.assertIn("math.mul", d1)
|
||||
self.assertEqual(d1["math.sum"](3, 8), 11)
|
||||
self.assertEqual(d1["math.diff"](6, 9), -3)
|
||||
self.assertEqual(d1["math.mul"](2, 3), 6)
|
||||
|
||||
d2 = Dispatcher(Math)
|
||||
self.assertNotIn("__class__", d2)
|
||||
self.assertEqual(d1.keys(), d2.keys())
|
||||
for method in ["math.sum", "math.diff"]:
|
||||
self.assertEqual(d1[method], d2[method])
|
||||
|
||||
def test_class_prefix(self):
|
||||
d = Dispatcher(Math, prefix="")
|
||||
self.assertIn("sum", d)
|
||||
self.assertNotIn("math.sum", d)
|
||||
|
||||
def test_object(self):
|
||||
math = Math()
|
||||
d1 = Dispatcher()
|
||||
d1.add_object(math)
|
||||
self.assertIn("math.sum", d1)
|
||||
self.assertIn("math.diff", d1)
|
||||
self.assertEqual(d1["math.sum"](3, 8), 11)
|
||||
self.assertEqual(d1["math.diff"](6, 9), -3)
|
||||
|
||||
d2 = Dispatcher(math)
|
||||
self.assertNotIn("__class__", d2)
|
||||
self.assertEqual(d1, d2)
|
||||
|
||||
def test_object_prefix(self):
|
||||
d = Dispatcher(Math(), prefix="")
|
||||
self.assertIn("sum", d)
|
||||
self.assertNotIn("math.sum", d)
|
||||
|
||||
def test_add_dict(self):
|
||||
d = Dispatcher()
|
||||
d.add_prototype({"sum": lambda *args: sum(args)}, "util.")
|
||||
|
||||
self.assertIn("util.sum", d)
|
||||
self.assertEqual(d["util.sum"](13, -2), 11)
|
||||
|
||||
def test_init_from_dict(self):
|
||||
d = Dispatcher({
|
||||
"one": lambda: 1,
|
||||
"two": lambda: 2,
|
||||
})
|
||||
|
||||
self.assertIn("one", d)
|
||||
self.assertIn("two", d)
|
||||
|
||||
def test_del_method(self):
|
||||
d = Dispatcher()
|
||||
d["method"] = lambda: ""
|
||||
self.assertIn("method", d)
|
||||
|
||||
del d["method"]
|
||||
self.assertNotIn("method", d)
|
||||
|
||||
def test_to_dict(self):
|
||||
d = Dispatcher()
|
||||
|
||||
def func():
|
||||
return ""
|
||||
|
||||
d["method"] = func
|
||||
self.assertEqual(dict(d), {"method": func})
|
||||
|
||||
def test__getattr_function(self):
|
||||
# class
|
||||
self.assertEqual(Dispatcher._getattr_function(Math, "sum")(3, 2), 5)
|
||||
self.assertEqual(Dispatcher._getattr_function(Math, "diff")(3, 2), 1)
|
||||
self.assertEqual(Dispatcher._getattr_function(Math, "mul")(3, 2), 6)
|
||||
|
||||
# object
|
||||
self.assertEqual(Dispatcher._getattr_function(Math(), "sum")(3, 2), 5)
|
||||
self.assertEqual(Dispatcher._getattr_function(Math(), "diff")(3, 2), 1)
|
||||
self.assertEqual(Dispatcher._getattr_function(Math(), "mul")(3, 2), 6)
|
||||
@@ -0,0 +1,239 @@
|
||||
"""Test Async JSON-RPC Response manager."""
|
||||
import unittest
|
||||
import json
|
||||
|
||||
from ..core import JSONRPC20Request, JSONRPC20Response, JSONRPC20MethodNotFound, JSONRPC20InvalidParams, JSONRPC20ServerError, JSONRPC20DispatchException
|
||||
from ..manager import AsyncJSONRPCResponseManager
|
||||
|
||||
|
||||
class TestAsyncJSONRPCResponseManager(unittest.IsolatedAsyncioTestCase):
|
||||
def setUp(self):
|
||||
def subtract(minuend, subtrahend):
|
||||
return minuend - subtrahend
|
||||
|
||||
def raise_(e: Exception):
|
||||
raise e
|
||||
|
||||
async def async_sum(*args):
|
||||
return sum(args)
|
||||
|
||||
self.dispatcher = {
|
||||
"subtract": subtract,
|
||||
"async_sum": async_sum,
|
||||
"dispatch_exception": lambda: raise_(
|
||||
JSONRPC20DispatchException(
|
||||
code=4000, message="error", data={"param": 1}
|
||||
)
|
||||
),
|
||||
"unexpected_exception": lambda: raise_(ValueError("Unexpected")),
|
||||
}
|
||||
|
||||
self.manager = AsyncJSONRPCResponseManager(dispatcher=self.dispatcher)
|
||||
|
||||
async def test_get_response(self):
|
||||
req = JSONRPC20Request("subtract", params=[5, 3], id=0)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertTrue(isinstance(res, JSONRPC20Response))
|
||||
self.assertEqual(res.result, 2)
|
||||
|
||||
async def test_get_response_notification(self):
|
||||
req = JSONRPC20Request("subtract", params=[5, 3], is_notification=True)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertIsNone(res)
|
||||
|
||||
async def test_get_async_response(self):
|
||||
req = JSONRPC20Request("async_sum", params=[1, 2, 3], id=0)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertTrue(isinstance(res, JSONRPC20Response))
|
||||
self.assertEqual(res.result, 6)
|
||||
|
||||
async def test_get_response_method_not_found(self):
|
||||
req = JSONRPC20Request("does_not_exist", id=0)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertTrue(isinstance(res, JSONRPC20Response))
|
||||
self.assertEqual(res.error, JSONRPC20MethodNotFound())
|
||||
self.assertEqual(res.id, req.id)
|
||||
|
||||
async def test_get_response_method_not_found_notification(self):
|
||||
req = JSONRPC20Request("does_not_exist", is_notification=True)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertIsNone(res)
|
||||
|
||||
async def test_get_response_incorrect_arguments(self):
|
||||
req = JSONRPC20Request("subtract", params=[0], id=0)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertTrue(isinstance(res, JSONRPC20Response))
|
||||
self.assertEqual(res.error, JSONRPC20InvalidParams())
|
||||
self.assertEqual(res.id, req.id)
|
||||
|
||||
async def test_get_response_incorrect_arguments_notification(self):
|
||||
req = JSONRPC20Request("subtract", params=[0], is_notification=True)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertIsNone(res)
|
||||
|
||||
async def test_get_response_method_expected_error(self):
|
||||
req = JSONRPC20Request("dispatch_exception", id=0)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertTrue(isinstance(res, JSONRPC20Response))
|
||||
self.assertEqual(res.error.body, dict(code=4000, message="error", data={"param": 1}))
|
||||
self.assertEqual(res.id, req.id)
|
||||
|
||||
async def test_get_response_method_expected_error_notification(self):
|
||||
req = JSONRPC20Request("dispatch_exception", is_notification=True)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertIsNone(res)
|
||||
|
||||
async def test_get_response_method_unexpected_error(self):
|
||||
req = JSONRPC20Request("unexpected_exception", id=0)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertTrue(isinstance(res, JSONRPC20Response))
|
||||
self.assertEqual(res.error, JSONRPC20ServerError())
|
||||
self.assertEqual(res.id, req.id)
|
||||
|
||||
async def test_get_response_method_unexpected_error_notification(self):
|
||||
req = JSONRPC20Request("unexpected_exception", is_notification=True)
|
||||
res = await self.manager.get_response_for_request(req)
|
||||
self.assertIsNone(res)
|
||||
|
||||
async def test_get_response_for_payload_batch(self):
|
||||
response = await self.manager.get_response_for_payload(json.dumps([
|
||||
{"jsonrpc": "2.0", "method": "subtract", "params": [3, 4], "id": 1},
|
||||
{"jsonrpc": "2.0"}
|
||||
]))
|
||||
self.assertEqual(
|
||||
response.body,
|
||||
[
|
||||
{"jsonrpc": "2.0", "result": -1, "id": 1},
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"error": {"code": -32600, "message": "Invalid Request"},
|
||||
"id": None
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
async def test_verbose_error(self):
|
||||
manager = AsyncJSONRPCResponseManager(
|
||||
dispatcher=self.dispatcher, is_server_error_verbose=True)
|
||||
req = JSONRPC20Request("unexpected_exception", id=0)
|
||||
res = await manager.get_response_for_request(req)
|
||||
self.assertEqual(
|
||||
res.error.data,
|
||||
{'type': 'ValueError', 'args': ('Unexpected',), 'message': 'Unexpected'}
|
||||
)
|
||||
|
||||
manager.is_server_error_verbose = False
|
||||
res = await manager.get_response_for_request(req)
|
||||
self.assertIsNone(res.error.data)
|
||||
|
||||
#############################################
|
||||
# Test examples from https://www.jsonrpc.org/specification
|
||||
#############################################
|
||||
|
||||
async def test_examples_positional_parameters(self):
|
||||
response1 = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}'
|
||||
)
|
||||
self.assertEqual(response1.body, {"jsonrpc": "2.0", "result": 19, "id": 1})
|
||||
|
||||
response2 = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": "subtract", "params": [23, 42], "id": 2}'
|
||||
)
|
||||
self.assertEqual(response2.body, {"jsonrpc": "2.0", "result": -19, "id": 2})
|
||||
|
||||
async def test_examples_named_parameters(self):
|
||||
response1 = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}'
|
||||
)
|
||||
self.assertEqual(response1.body, {"jsonrpc": "2.0", "result": 19, "id": 3})
|
||||
|
||||
response2 = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": "subtract", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}'
|
||||
)
|
||||
self.assertEqual(response2.body, {"jsonrpc": "2.0", "result": 19, "id": 4})
|
||||
|
||||
async def test_examples_notification(self):
|
||||
response1 = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]}'
|
||||
)
|
||||
self.assertIsNone(response1)
|
||||
|
||||
response2 = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": "foobar"}'
|
||||
)
|
||||
self.assertIsNone(response2)
|
||||
|
||||
async def test_examples_rpc_call_of_nonexistent_method(self):
|
||||
response = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": "foobar", "id": "1"}'
|
||||
)
|
||||
self.assertEqual(response.body, {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "1"})
|
||||
|
||||
async def test_exampels_rpc_call_with_invalid_json(self):
|
||||
response = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": "foobar, "params": "bar", "baz]'
|
||||
)
|
||||
self.assertEqual(response.body, {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error"}, "id": None})
|
||||
|
||||
async def test_examples_rpc_call_with_invalid_request_object(self):
|
||||
response = await self.manager.get_response_for_payload(
|
||||
'{"jsonrpc": "2.0", "method": 1, "params": "bar"}'
|
||||
)
|
||||
self.assertEqual(response.body, {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": None})
|
||||
|
||||
async def test_examples_rpc_call_batch_invalid_json(self):
|
||||
response = await self.manager.get_response_for_payload(
|
||||
"""[
|
||||
{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
|
||||
{"jsonrpc": "2.0", "method"
|
||||
]"""
|
||||
)
|
||||
self.assertEqual(response.body, {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error"}, "id": None})
|
||||
|
||||
async def test_examples_rpc_call_with_an_empty_array(self):
|
||||
response = await self.manager.get_response_for_payload('[]')
|
||||
self.assertEqual(response.body, {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": None})
|
||||
|
||||
async def test_examples_rpc_call_with_an_invalid_batch_but_not_empty(self):
|
||||
response = await self.manager.get_response_for_payload('[1]')
|
||||
self.assertEqual(response.body, [{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": None}])
|
||||
|
||||
async def test_examples_rpc_call_with_invalid_batch(self):
|
||||
response = await self.manager.get_response_for_payload('[1,2,3]')
|
||||
self.assertEqual(response.body, [
|
||||
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": None},
|
||||
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": None},
|
||||
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": None}
|
||||
])
|
||||
|
||||
async def test_examples_rpc_call_batch(self):
|
||||
dispatcher = {
|
||||
"sum": lambda *values: sum(values),
|
||||
"subtract": lambda a, b: a - b,
|
||||
"get_data": lambda: ["hello", 5],
|
||||
}
|
||||
manager = AsyncJSONRPCResponseManager(dispatcher=dispatcher)
|
||||
|
||||
response = await manager.get_response_for_payload(json.dumps([
|
||||
{"jsonrpc": "2.0", "method": "sum", "params": [1, 2, 4], "id": "1"},
|
||||
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
|
||||
{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": "2"},
|
||||
{"foo": "boo"},
|
||||
{"jsonrpc": "2.0", "method": "foo.get", "params": {"name": "myself"}, "id": "5"},
|
||||
{"jsonrpc": "2.0", "method": "get_data", "id": "9"},
|
||||
]))
|
||||
|
||||
self.assertEqual(response.body, [
|
||||
{"jsonrpc": "2.0", "result": 7, "id": "1"},
|
||||
{"jsonrpc": "2.0", "result": 19, "id": "2"},
|
||||
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}, "id": None},
|
||||
{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "5"},
|
||||
{"jsonrpc": "2.0", "result": ["hello", 5], "id": "9"}
|
||||
])
|
||||
|
||||
async def test_examples_rpc_call_batch_all_notifications(self):
|
||||
response = await self.manager.get_response_for_payload(json.dumps([
|
||||
{"jsonrpc": "2.0", "method": "notify_sum", "params": [1, 2, 4]},
|
||||
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
|
||||
]))
|
||||
self.assertIsNone(response)
|
||||
Reference in New Issue
Block a user