git.fiddlerwoaroof.com
Browse code

Merge pull request #3 from fiddlerwoaroof/master

Fixed up unit testing, ironed out a few bugs, and supported more of the server spec (notifications and error codes)

fiddlerwoaroof authored on 01/06/2011 01:48:21
Showing 2 changed files
2 2
new file mode 100644
... ...
@@ -0,0 +1,261 @@
1
+from twisted.trial import unittest
2
+import StringIO
3
+
4
+import mock
5
+
6
+import jsonrpc.server
7
+import jsonrpc.jsonutil
8
+
9
+from twisted.web.test.test_web import DummyRequest
10
+from twisted.internet.defer import succeed
11
+from twisted.web.static import server
12
+
13
+def _render(resource, request):
14
+    result = resource.render(request)
15
+    if isinstance(result, str):
16
+        request.write(result)
17
+        request.finish()
18
+        return succeed(None)
19
+    elif result is server.NOT_DONE_YET:
20
+        if request.finished:
21
+            return succeed(None)
22
+        else:
23
+            return request.notifyFinish()
24
+    else:
25
+        raise ValueError("Unexpected return value: %r" % (result,))
26
+
27
+class SimpleEventHandler(jsonrpc.server.ServerEvents):
28
+	def log(self, result, request): pass
29
+
30
+	def findmethod(self, method):
31
+		if method in set(['echo', 'add']):
32
+			return getattr(self, method)
33
+
34
+	def add(self, a,b):
35
+		return a+b
36
+
37
+	def echo(self, v): return v
38
+
39
+
40
+class TestJSONRPCServer(unittest.TestCase):
41
+
42
+	def setUp(self):
43
+		self.id_ = 'an_id'
44
+		self.param = "some data"
45
+
46
+	def test_invalid_data(self):
47
+		resource = jsonrpc.server.JSON_RPC()
48
+		resource.customize(SimpleEventHandler)
49
+
50
+		request = DummyRequest([''])
51
+		request.getCookie = mock.Mock()
52
+		request.content = StringIO.StringIO(' {"v": %s}, "method": "echo"}' % (jsonrpc.jsonutil.encode(self.param)))
53
+
54
+		d = _render(resource, request)
55
+
56
+		@d.addCallback
57
+		def rendered(ignored):
58
+			assert len(request.written) == 1
59
+			data = jsonrpc.jsonutil.decode(request.written[0])
60
+
61
+			assert data == {"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error."}, "id": None}
62
+
63
+		return d
64
+
65
+	def test_wrongversion(self):
66
+		resource = jsonrpc.server.JSON_RPC()
67
+		resource.customize(SimpleEventHandler)
68
+
69
+		request = DummyRequest([''])
70
+		request.getCookie = mock.Mock()
71
+		request.content = StringIO.StringIO('{"jsonrpc": "2.1", "params": %s, "method": "echo", "id": "%s"}' % (jsonrpc.jsonutil.encode([self.param]), self.id_))
72
+
73
+		d = _render(resource, request)
74
+
75
+		@d.addCallback
76
+		def rendered(ignored):
77
+			assert len(request.written) == 1
78
+			data = jsonrpc.jsonutil.decode(request.written[0])
79
+			assert data == {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": self.id_}
80
+		return d
81
+
82
+
83
+	def test_invalidmethodname(self):
84
+		resource = jsonrpc.server.JSON_RPC()
85
+		resource.customize(SimpleEventHandler)
86
+
87
+		request = DummyRequest([''])
88
+		request.getCookie = mock.Mock()
89
+		request.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": %s, "method": 0, "id": "%s"}' % (jsonrpc.jsonutil.encode([self.param]), self.id_))
90
+
91
+		d = _render(resource, request)
92
+
93
+		@d.addCallback
94
+		def rendered(ignored):
95
+			assert len(request.written) == 1
96
+			data = jsonrpc.jsonutil.decode(request.written[0])
97
+			assert data == {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": self.id_}
98
+		return d
99
+
100
+	def test_missingmethod(self):
101
+		resource = jsonrpc.server.JSON_RPC()
102
+		resource.customize(SimpleEventHandler)
103
+
104
+		request = DummyRequest([''])
105
+		request.getCookie = mock.Mock()
106
+		request.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": %s, "method": "non_existent", "id": "%s"}' % (jsonrpc.jsonutil.encode([self.param]), self.id_))
107
+
108
+		d = _render(resource, request)
109
+
110
+		@d.addCallback
111
+		def rendered(ignored):
112
+			assert len(request.written) == 1
113
+			data = jsonrpc.jsonutil.decode(request.written[0])
114
+			assert data == {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Procedure not found."}, "id": self.id_}
115
+		return d
116
+
117
+
118
+
119
+	def test_simplecall(self):
120
+		resource = jsonrpc.server.JSON_RPC()
121
+		resource.customize(SimpleEventHandler)
122
+
123
+		request = DummyRequest([''])
124
+		request.getCookie = mock.Mock()
125
+		request.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": %s, "method": "echo", "id": "%s"}' % (jsonrpc.jsonutil.encode([self.param]), self.id_))
126
+
127
+		d = _render(resource, request)
128
+
129
+		@d.addCallback
130
+		def rendered(ignored):
131
+			assert len(request.written) == 1
132
+			data = jsonrpc.jsonutil.decode(request.written[0])
133
+
134
+			assert data['id'] == self.id_
135
+			assert data['result'] == self.param
136
+		return d
137
+
138
+	def test_notify(self):
139
+		resource = jsonrpc.server.JSON_RPC()
140
+		resource.customize(SimpleEventHandler)
141
+
142
+		request = DummyRequest([''])
143
+		request.getCookie = mock.Mock()
144
+		request.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": {"v": %s}, "method": "echo"}' % (jsonrpc.jsonutil.encode(self.param)))
145
+
146
+		d = _render(resource, request)
147
+
148
+		@d.addCallback
149
+		def rendered(ignored):
150
+			assert len(request.written) == 0
151
+
152
+		return d
153
+
154
+
155
+	def test_kwcall(self):
156
+		resource = jsonrpc.server.JSON_RPC()
157
+		resource.customize(SimpleEventHandler)
158
+
159
+		request = DummyRequest([''])
160
+		request.getCookie = mock.Mock()
161
+		request.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": {"v": %s}, "method": "echo", "id": "%s"}' % (jsonrpc.jsonutil.encode(self.param), self.id_))
162
+
163
+		d = _render(resource, request)
164
+
165
+		@d.addCallback
166
+		def rendered(ignored):
167
+			assert len(request.written) == 1
168
+			data = jsonrpc.jsonutil.decode(request.written[0])
169
+
170
+			assert data['id'] == self.id_
171
+			assert data['result'] == self.param
172
+
173
+		return d
174
+
175
+
176
+	def test_err(self):
177
+		resource = jsonrpc.server.JSON_RPC()
178
+		resource.customize(SimpleEventHandler)
179
+
180
+		request = DummyRequest([''])
181
+		request.getCookie = mock.Mock()
182
+		request.content = StringIO.StringIO('{"jsonrpc": "2.0", "params": [1, "sss"], "method": "add", "id": "%s"}' % self.id_)
183
+
184
+		d = _render(resource, request)
185
+
186
+		@d.addCallback
187
+		def rendered(ignored, *a):
188
+			assert len(request.written) == 1
189
+			data = jsonrpc.jsonutil.decode(request.written[0])
190
+
191
+			assert data['id'] == self.id_
192
+			assert data.get('error', False)
193
+		return rendered
194
+
195
+	def test_batchcall(self):
196
+		resource = jsonrpc.server.JSON_RPC()
197
+		resource.customize(SimpleEventHandler)
198
+
199
+		request = DummyRequest([''])
200
+		request.content = StringIO.StringIO(
201
+			'[{"jsonrpc": "2.0", "params": [1, 2], "method": "add", "id": "1"},'
202
+				'{"jsonrpc": "2.0", "params": {"a": 3, "b": 2}, "method": "add", "id": "2"}]'
203
+		)
204
+		request.getCookie = mock.Mock()
205
+
206
+		d = _render(resource, request)
207
+
208
+		@d.addCallback
209
+		def rendered(ignored, *a):
210
+			assert len(request.written) == 1
211
+			data = jsonrpc.jsonutil.decode(request.written[0])
212
+			assert len(data) == 2
213
+			assert set(x['id'] for x in data) == set("12")
214
+			assert set(x['result'] for x in data) == set([3,5])
215
+
216
+			assert not any(x.get('error', False) for x in data)
217
+		return rendered
218
+
219
+	def test_batchcall_1err(self):
220
+		resource = jsonrpc.server.JSON_RPC()
221
+		resource.customize(SimpleEventHandler)
222
+
223
+		request = DummyRequest([''])
224
+		request.content = StringIO.StringIO(
225
+			'[{"jsonrpc": "2.0", "params": [1, 2], "method": "add", "id": "1"},'
226
+				'{"jsonrpc": "2.0", "params": {"a": "3", "b": 2}, "method": "add", "id": "2"}]'
227
+		)
228
+		request.getCookie = mock.Mock()
229
+
230
+		d = _render(resource, request)
231
+
232
+		@d.addCallback
233
+		def rendered(ignored, *a):
234
+			assert len(request.written) == 1
235
+			data = jsonrpc.jsonutil.decode(request.written[0])
236
+			assert len(data) == 2
237
+			assert set(x['id'] for x in data) == set("12")
238
+			assert set(x.get('result', False) for x in data) == set([3,False])
239
+
240
+			assert len(filter(None, [x.get('error') for x in data])) == 1
241
+		return rendered
242
+
243
+
244
+	def test_batchcall_emptylist(self):
245
+		resource = jsonrpc.server.JSON_RPC()
246
+		resource.customize(SimpleEventHandler)
247
+
248
+		request = DummyRequest([''])
249
+
250
+		request.content = StringIO.StringIO('[]')
251
+		request.getCookie = mock.Mock()
252
+
253
+		d = _render(resource, request)
254
+
255
+		@d.addCallback
256
+		def rendered(ignored, *a):
257
+			data = jsonrpc.jsonutil.decode(request.written[0])
258
+			assert data == {"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": None}
259
+		return rendered
260
+
261
+