commit d94a42d734765a00bd340260916e1de55a374cbf
parent ae57339500442ef58e300360b7a479ac7e2aa88d
Author: nolash <dev@holbrook.no>
Date: Fri, 9 Apr 2021 15:57:41 +0200
Improve tests
Diffstat:
5 files changed, 145 insertions(+), 9 deletions(-)
diff --git a/jsonrpc_std/error.py b/jsonrpc_std/error.py
@@ -1,16 +1,30 @@
# local imports
from .base import JSONRPCBase
+
class JSONRPCException(Exception, JSONRPCBase):
message = 'Unknown'
- def __init__(self, v):
+ def __init__(self, v, request_id=None):
context_v = '{} error'.format(self.message)
if v != None:
context_v += ': ' + v
+ self.request_id = request_id
+
super(JSONRPCException, self).__init__(context_v)
+ # Thanks to https://stackoverflow.com/questions/35282222/in-python-how-do-i-cast-a-class-object-to-a-dict
+ def __iter__(self):
+ if self.request_id == None:
+ raise AttributeError('request id cannot be undefined when serializing error')
+ yield 'jsonrpc', JSONRPCBase.version_string
+ yield 'id', self.request_id
+ yield 'error', {
+ 'code': self.code,
+ 'message': str(self),
+ }
+
class JSONRPCCustomException(JSONRPCException):
code = -32000
@@ -80,7 +94,3 @@ class JSONRPCErrors:
if e == None:
raise JSONRPCUnhandledErrorException(code)
return e(v)
-
-
-class InvalidJSONRPCError(ValueError):
- pass
diff --git a/jsonrpc_std/parse.py b/jsonrpc_std/parse.py
@@ -22,6 +22,8 @@ def jsonrpc_validate_dict(o):
method = o.get('method')
if method == None:
raise JSONRPCParseError('missing method field')
+ elif type(method).__name__ != 'str':
+ raise JSONRPCInvalidRequestError('method must be str')
params = o.get('params')
if params == None:
@@ -44,11 +46,12 @@ def jsonrpc_from_str(s):
def jsonrpc_from_dict(o):
- o = jsonrpc_validate_dict(o)
- req = jsonrpc_request(o['method'], request_id=o['id'])
- req['params'] = o['params']
+ o_parsed = jsonrpc_validate_dict(o)
+ req = jsonrpc_request(o_parsed['method'], request_id=o_parsed['id'])
+ req['params'] = o_parsed['params']
return req
+
def jsonrpc_from_file(f):
o = json.load(f)
return jsonrpc_from_dict(o)
diff --git a/setup.cfg b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = jsonrpc_std
-version = 0.0.1a1
+version = 0.0.1a2
description = Pure python standard library JSONRPC data interface
author = Louis Holbrook
author_email = dev@holbrook.no
diff --git a/tests/test_error.py b/tests/test_error.py
@@ -1,5 +1,6 @@
# standard imports
import unittest
+import json
# local imports
from jsonrpc_std.error import (
@@ -68,5 +69,14 @@ class TestError(unittest.TestCase):
print('e {}'.format(o))
+ def test_error_serialize(self):
+ e = JSONRPCParseError('foo', request_id='bar')
+ o = dict(e)
+ self.assertEqual(o['jsonrpc'], '2.0')
+ self.assertEqual(o['id'], 'bar')
+ self.assertEqual(o['error']['code'], -32700)
+ self.assertEqual(o['error']['message'], 'Parse error: foo')
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_parse.py b/tests/test_parse.py
@@ -0,0 +1,113 @@
+# standard imports
+import unittest
+import io
+
+# local imports
+from jsonrpc_std.parse import *
+from jsonrpc_std.error import (
+ JSONRPCParseError,
+ )
+
+
+class TestParse(unittest.TestCase):
+
+
+ def setUp(self):
+ self.valid_o = {
+ 'jsonrpc': '2.0',
+ 'id': 42,
+ 'method': 'foo_bazBaz',
+ 'params': [13, {
+ 'xyzzy': 666,
+ 'inky': ['pinky', 'blinky', 'clyde'],
+ },
+ ],
+ }
+
+ def test_from_dict(self):
+ r = jsonrpc_from_dict(self.valid_o)
+ self.assertEqual(r['id'], self.valid_o['id'])
+ self.assertEqual(r['params'], self.valid_o['params'])
+ self.assertEqual(r['method'], self.valid_o['method'])
+
+ s = json.dumps(self.valid_o)
+ r = jsonrpc_from_str(s)
+ self.assertEqual(r['id'], self.valid_o['id'])
+ self.assertEqual(r['params'], self.valid_o['params'])
+ self.assertEqual(r['method'], self.valid_o['method'])
+
+ r = jsonrpc_from_file(io.BytesIO(s.encode('utf-8')))
+ self.assertEqual(r['id'], self.valid_o['id'])
+ self.assertEqual(r['params'], self.valid_o['params'])
+ self.assertEqual(r['method'], self.valid_o['method'])
+
+
+
+ def test_missing_version(self):
+ o = self.valid_o
+ del o['jsonrpc']
+ with self.assertRaises(JSONRPCParseError):
+ jsonrpc_from_dict(o)
+
+
+ def test_id(self):
+ o = self.valid_o
+ del o['id']
+ with self.assertRaises(JSONRPCParseError):
+ jsonrpc_from_dict(o)
+
+ o['id'] = None
+ with self.assertRaises(JSONRPCParseError):
+ jsonrpc_from_dict(o)
+
+ o['id'] = {}
+ with self.assertRaises(JSONRPCInvalidRequestError):
+ jsonrpc_from_dict(o)
+
+ o['id'] = JSONRPCBase()
+ with self.assertRaises(JSONRPCInvalidRequestError):
+ jsonrpc_from_dict(o)
+
+
+ def test_method(self):
+ o = self.valid_o
+ del o['method']
+
+ with self.assertRaises(JSONRPCParseError):
+ jsonrpc_from_dict(o)
+
+ o['method'] = None
+ with self.assertRaises(JSONRPCParseError):
+ jsonrpc_from_dict(o)
+
+ o['method'] = 42
+ with self.assertRaises(JSONRPCInvalidRequestError):
+ jsonrpc_from_dict(o)
+
+
+ o['method'] = {}
+ with self.assertRaises(JSONRPCInvalidRequestError):
+ jsonrpc_from_dict(o)
+
+ o['method'] = JSONRPCBase()
+ with self.assertRaises(JSONRPCInvalidRequestError):
+ jsonrpc_from_dict(o)
+
+ def test_params(self):
+ o = self.valid_o
+ del o['params']
+
+ with self.assertRaises(JSONRPCParseError):
+ jsonrpc_from_dict(o)
+
+ o['params'] = None
+ with self.assertRaises(JSONRPCParseError):
+ jsonrpc_from_dict(o)
+
+ o['params'] = {}
+ with self.assertRaises(JSONRPCParseError):
+ jsonrpc_from_dict(o)
+
+
+if __name__ == '__main__':
+ unittest.main()