Skip to content

Commit fc13454

Browse files
committed
Corrected tests on Python 2
Python 2 has an io module, messing with StringIO
1 parent 2d37bb8 commit fc13454

File tree

1 file changed

+171
-70
lines changed

1 file changed

+171
-70
lines changed

tests.py

Lines changed: 171 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,188 @@
1+
#!/usr/bin/python
2+
# -- Content-Encoding: UTF-8 --
13
"""
24
The tests in this file compare the request and response objects
35
to the JSON-RPC 2.0 specification document, as well as testing
4-
several internal components of the jsonrpclib library. Run this
6+
several internal components of the jsonrpclib library. Run this
57
module without any parameters to run the tests.
68
7-
Currently, this is not easily tested with a framework like
9+
Currently, this is not easily tested with a framework like
810
nosetests because we spin up a daemon thread running the
911
the Server, and nosetests (at least in my tests) does not
1012
ever "kill" the thread.
1113
1214
If you are testing jsonrpclib and the module doesn't return to
13-
the command prompt after running the tests, you can hit
15+
the command prompt after running the tests, you can hit
1416
"Ctrl-C" (or "Ctrl-Break" on Windows) and that should kill it.
1517
1618
TODO:
1719
* Finish implementing JSON-RPC 2.0 Spec tests
1820
* Implement JSON-RPC 1.0 tests
1921
* Implement JSONClass, History, Config tests
22+
23+
:license: Apache License 2.0
24+
:version: 1.0.0
2025
"""
2126

27+
# Module version
28+
__version_info__ = (1, 0, 0)
29+
__version__ = ".".join(str(x) for x in __version_info__)
30+
31+
# Documentation strings format
32+
__docformat__ = "restructuredtext en"
33+
34+
# ------------------------------------------------------------------------------
35+
36+
# jsonrpclib
2237
from jsonrpclib import Server, MultiCall, ProtocolError
2338
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
24-
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCRequestHandler
2539
from jsonrpclib.utils import from_bytes
26-
27-
import socket
28-
import unittest
29-
import time
3040
import jsonrpclib.history
3141

42+
# Standard library
3243
import contextlib
3344
import re
3445
import sys
46+
import threading
47+
import time
48+
import unittest
3549

36-
if sys.version_info[0] < 3:
50+
try:
51+
# Python 2
3752
from StringIO import StringIO
3853

39-
else:
54+
except ImportError:
55+
# Python 3
4056
from io import StringIO
4157

4258
try:
4359
import json
60+
4461
except ImportError:
4562
import simplejson as json
46-
from threading import Thread
63+
64+
# ------------------------------------------------------------------------------
4765

4866
PORTS = list(range(8000, 8999))
4967

68+
# ------------------------------------------------------------------------------
69+
# Test methods
70+
71+
def subtract(minuend, subtrahend):
72+
"""
73+
Using the keywords from the JSON-RPC v2 doc
74+
"""
75+
return minuend - subtrahend
76+
77+
def add(x, y):
78+
return x + y
79+
80+
def update(*args):
81+
return args
82+
83+
def summation(*args):
84+
return sum(args)
85+
86+
def notify_hello(*args):
87+
return args
88+
89+
def get_data():
90+
return ['hello', 5]
91+
92+
def ping():
93+
return True
94+
95+
# ------------------------------------------------------------------------------
96+
# Server utility class
97+
98+
class UtilityServer(object):
99+
"""
100+
Utility start/stop server
101+
"""
102+
def __init__(self):
103+
"""
104+
Sets up members
105+
"""
106+
self._server = None
107+
self._thread = None
108+
109+
110+
def start(self, addr, port):
111+
"""
112+
Starts the server
113+
114+
:param addr: A binding address
115+
:param port: A listening port
116+
:return: This object (for in-line calls)
117+
"""
118+
# Create the server
119+
self._server = server = SimpleJSONRPCServer((addr, port),
120+
logRequests=False)
121+
122+
# Register test methods
123+
server.register_function(summation, 'sum')
124+
server.register_function(summation, 'notify_sum')
125+
server.register_function(notify_hello)
126+
server.register_function(subtract)
127+
server.register_function(update)
128+
server.register_function(get_data)
129+
server.register_function(add)
130+
server.register_function(ping)
131+
server.register_function(summation, 'namespace.sum')
132+
133+
# Serve in a thread
134+
self._thread = threading.Thread(target=server.serve_forever)
135+
self._thread.daemon = True
136+
self._thread.start()
137+
138+
# Allow an in-line instantiation
139+
return self
140+
141+
142+
def stop(self):
143+
"""
144+
Stops the server and waits for its thread to finish
145+
"""
146+
self._server.shutdown()
147+
self._server.server_close()
148+
self._thread.join()
149+
150+
self._server = None
151+
self._thread = None
152+
153+
# ------------------------------------------------------------------------------
154+
50155
class TestCompatibility(unittest.TestCase):
51156

52157
client = None
53158
port = None
54159
server = None
55160

56161
def setUp(self):
162+
"""
163+
Pre-test set up
164+
"""
165+
# Set up the server
57166
self.port = PORTS.pop()
167+
self.server = UtilityServer().start('', self.port)
168+
169+
# Set up the client
58170
self.history = jsonrpclib.history.History()
59-
self.server = server_set_up(addr=('', self.port))
60171
self.client = Server('http://localhost:{0}'.format(self.port),
61172
history=self.history)
62173

174+
175+
def tearDown(self):
176+
"""
177+
Post-test clean up
178+
"""
179+
# Close the client
180+
self.client("close")
181+
182+
# Stop the server
183+
self.server.stop()
184+
185+
63186
# v1 tests forthcoming
64187

65188
# Version 2.0 Tests
@@ -132,7 +255,7 @@ def test_non_existent_method(self):
132255
def test_invalid_json(self):
133256
invalid_json = '{"jsonrpc": "2.0", "method": "foobar, ' + \
134257
'"params": "bar", "baz]'
135-
response = self.client._run_request(invalid_json)
258+
self.client._run_request(invalid_json)
136259
response = json.loads(self.history.response)
137260
verify_response = json.loads(
138261
'{"jsonrpc": "2.0", "error": {"code": -32700,' +
@@ -143,7 +266,7 @@ def test_invalid_json(self):
143266

144267
def test_invalid_request(self):
145268
invalid_request = '{"jsonrpc": "2.0", "method": 1, "params": "bar"}'
146-
response = self.client._run_request(invalid_request)
269+
self.client._run_request(invalid_request)
147270
response = json.loads(self.history.response)
148271
verify_response = json.loads(
149272
'{"jsonrpc": "2.0", "error": {"code": -32600, ' +
@@ -155,7 +278,7 @@ def test_invalid_request(self):
155278
def test_batch_invalid_json(self):
156279
invalid_request = '[ {"jsonrpc": "2.0", "method": "sum", ' + \
157280
'"params": [1,2,4], "id": "1"},{"jsonrpc": "2.0", "method" ]'
158-
response = self.client._run_request(invalid_request)
281+
self.client._run_request(invalid_request)
159282
response = json.loads(self.history.response)
160283
verify_response = json.loads(
161284
'{"jsonrpc": "2.0", "error": {"code": -32700,' +
@@ -166,7 +289,7 @@ def test_batch_invalid_json(self):
166289

167290
def test_empty_array(self):
168291
invalid_request = '[]'
169-
response = self.client._run_request(invalid_request)
292+
self.client._run_request(invalid_request)
170293
response = json.loads(self.history.response)
171294
verify_response = json.loads(
172295
'{"jsonrpc": "2.0", "error": {"code": -32600, ' +
@@ -178,7 +301,7 @@ def test_empty_array(self):
178301
def test_nonempty_array(self):
179302
invalid_request = '[1,2]'
180303
request_obj = json.loads(invalid_request)
181-
response = self.client._run_request(invalid_request)
304+
self.client._run_request(invalid_request)
182305
response = json.loads(self.history.response)
183306
self.assertTrue(len(response) == len(request_obj))
184307
for resp in response:
@@ -208,7 +331,7 @@ def test_batch(self):
208331
{"jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": "2"},
209332
{"foo": "boo"},
210333
{"jsonrpc": "2.0", "method": "foo.get", "params": {"name": "myself"}, "id": "5"},
211-
{"jsonrpc": "2.0", "method": "get_data", "id": "9"}
334+
{"jsonrpc": "2.0", "method": "get_data", "id": "9"}
212335
]""")
213336

214337
# Thankfully, these are in order so testing is pretty simple.
@@ -267,19 +390,32 @@ def test_batch_notifications(self):
267390
self.assertTrue(req == valid_req)
268391
self.assertTrue(self.history.response == '')
269392

393+
# ------------------------------------------------------------------------------
394+
270395
class InternalTests(unittest.TestCase):
271-
"""
272-
These tests verify that the client and server portions of
396+
"""
397+
These tests verify that the client and server portions of
273398
jsonrpclib talk to each other properly.
274399
"""
275-
client = None
276400
server = None
277401
port = None
278402

279403
def setUp(self):
404+
# Set up the server
280405
self.port = PORTS.pop()
406+
self.server = UtilityServer().start('', self.port)
407+
408+
# Prepare the client
281409
self.history = jsonrpclib.history.History()
282-
self.server = server_set_up(addr=('', self.port))
410+
411+
412+
def tearDown(self):
413+
"""
414+
Post-test clean up
415+
"""
416+
# Stop the server
417+
self.server.stop()
418+
283419

284420
def get_client(self):
285421
return Server('http://localhost:{0}'.format(self.port),
@@ -315,7 +451,7 @@ def test_single_notify(self):
315451

316452
def test_single_namespace(self):
317453
client = self.get_client()
318-
response = client.namespace.sum(1, 2, 4)
454+
client.namespace.sum(1, 2, 4)
319455
request = json.loads(self.history.request)
320456
response = json.loads(self.history.response)
321457
verify_request = {
@@ -361,12 +497,12 @@ def func():
361497
return result[i]
362498
self.assertRaises(raises[i], func)
363499

500+
# ------------------------------------------------------------------------------
364501

365502
class HeadersTests(unittest.TestCase):
366503
"""
367504
These tests verify functionality of additional headers.
368505
"""
369-
client = None
370506
server = None
371507
port = None
372508

@@ -376,8 +512,17 @@ def setUp(self):
376512
"""
377513
Sets up the test
378514
"""
515+
# Set up the server
379516
self.port = PORTS.pop()
380-
self.server = server_set_up(addr=('', self.port))
517+
self.server = UtilityServer().start('', self.port)
518+
519+
520+
def tearDown(self):
521+
"""
522+
Post-test clean up
523+
"""
524+
# Stop the server
525+
self.server.stop()
381526

382527

383528
@contextlib.contextmanager
@@ -577,51 +722,7 @@ def test_should_allow_to_nest_additional_header_blocks(self):
577722
self.assertTrue('x-level-2' in headers2)
578723
self.assertEqual(headers2['x-level-2'], '2')
579724

580-
581-
""" Test Methods """
582-
def subtract(minuend, subtrahend):
583-
""" Using the keywords from the JSON-RPC v2 doc """
584-
return minuend - subtrahend
585-
586-
def add(x, y):
587-
return x + y
588-
589-
def update(*args):
590-
return args
591-
592-
def summation(*args):
593-
return sum(args)
594-
595-
def notify_hello(*args):
596-
return args
597-
598-
def get_data():
599-
return ['hello', 5]
600-
601-
def ping():
602-
return True
603-
604-
def server_set_up(addr, address_family=socket.AF_INET):
605-
# Not sure this is a good idea to spin up a new server thread
606-
# for each test... but it seems to work fine.
607-
def log_request(self, *args, **kwargs):
608-
""" Making the server output 'quiet' """
609-
pass
610-
SimpleJSONRPCRequestHandler.log_request = log_request
611-
server = SimpleJSONRPCServer(addr, address_family=address_family)
612-
server.register_function(summation, 'sum')
613-
server.register_function(summation, 'notify_sum')
614-
server.register_function(notify_hello)
615-
server.register_function(subtract)
616-
server.register_function(update)
617-
server.register_function(get_data)
618-
server.register_function(add)
619-
server.register_function(ping)
620-
server.register_function(summation, 'namespace.sum')
621-
server_proc = Thread(target=server.serve_forever)
622-
server_proc.daemon = True
623-
server_proc.start()
624-
return server_proc
725+
# ------------------------------------------------------------------------------
625726

626727
if __name__ == '__main__':
627728
print("===============================================================")

0 commit comments

Comments
 (0)