Mercurial > libervia-pubsub
comparison src/test/test_gateway.py @ 369:dabee42494ac
config file + cleaning:
- SàT Pubsub can now be configured using the same config file as SàT itself (i.e. sat.conf or .sat.conf), in the same locations (/etc, local dir, xdg dir).
Its options must be in the "pubsub" section
- options on command line override config options
- removed tap and http files which are not used anymore
- changed directory structure to put source in src, to be coherent with SàT and Libervia
- changed options name, db* become db_*, secret become xmpp_pwd
- an exception is raised if jid or xmpp_pwd is are not configured
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Mar 2018 12:59:38 +0100 |
parents | sat_pubsub/test/test_gateway.py@618a92080812 |
children | aa3a464df605 |
comparison
equal
deleted
inserted
replaced
368:618a92080812 | 369:dabee42494ac |
---|---|
1 #!/usr/bin/python | |
2 #-*- coding: utf-8 -*- | |
3 | |
4 # Copyright (c) 2003-2011 Ralph Meijer | |
5 # Copyright (c) 2012-2018 Jérôme Poisson | |
6 | |
7 | |
8 # This program is free software: you can redistribute it and/or modify | |
9 # it under the terms of the GNU Affero General Public License as published by | |
10 # the Free Software Foundation, either version 3 of the License, or | |
11 # (at your option) any later version. | |
12 | |
13 # This program is distributed in the hope that it will be useful, | |
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 # GNU Affero General Public License for more details. | |
17 | |
18 # You should have received a copy of the GNU Affero General Public License | |
19 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 # -- | |
21 | |
22 # This program is based on Idavoll (http://idavoll.ik.nu/), | |
23 # originaly written by Ralph Meijer (http://ralphm.net/blog/) | |
24 # It is sublicensed under AGPL v3 (or any later version) as allowed by the original | |
25 # license. | |
26 | |
27 # -- | |
28 | |
29 # Here is a copy of the original license: | |
30 | |
31 # Copyright (c) 2003-2011 Ralph Meijer | |
32 | |
33 # Permission is hereby granted, free of charge, to any person obtaining | |
34 # a copy of this software and associated documentation files (the | |
35 # "Software"), to deal in the Software without restriction, including | |
36 # without limitation the rights to use, copy, modify, merge, publish, | |
37 # distribute, sublicense, and/or sell copies of the Software, and to | |
38 # permit persons to whom the Software is furnished to do so, subject to | |
39 # the following conditions: | |
40 | |
41 # The above copyright notice and this permission notice shall be | |
42 # included in all copies or substantial portions of the Software. | |
43 | |
44 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
45 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
46 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
47 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
48 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
49 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
50 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
51 | |
52 | |
53 """ | |
54 Tests for L{idavoll.gateway}. | |
55 | |
56 Note that some tests are functional tests that require a running idavoll | |
57 service. | |
58 """ | |
59 | |
60 from StringIO import StringIO | |
61 | |
62 import simplejson | |
63 | |
64 from twisted.internet import defer | |
65 from twisted.trial import unittest | |
66 from twisted.web import error, http, http_headers, server | |
67 from twisted.web.test import requesthelper | |
68 from twisted.words.xish import domish | |
69 from twisted.words.protocols.jabber.jid import JID | |
70 | |
71 from sat_pubsub import gateway | |
72 from sat_pubsub.backend import BackendService | |
73 from sat_pubsub.memory_storage import Storage | |
74 | |
75 AGENT = "Idavoll Test Script" | |
76 NS_ATOM = "http://www.w3.org/2005/Atom" | |
77 | |
78 TEST_ENTRY = domish.Element((NS_ATOM, 'entry')) | |
79 TEST_ENTRY.addElement("id", | |
80 content="urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a") | |
81 TEST_ENTRY.addElement("title", content="Atom-Powered Robots Run Amok") | |
82 TEST_ENTRY.addElement("author").addElement("name", content="John Doe") | |
83 TEST_ENTRY.addElement("content", content="Some text.") | |
84 | |
85 baseURI = "http://localhost:8086/" | |
86 component = "pubsub" | |
87 componentJID = JID(component) | |
88 ownerJID = JID('owner@example.org') | |
89 | |
90 def _render(resource, request): | |
91 result = resource.render(request) | |
92 if isinstance(result, str): | |
93 request.write(result) | |
94 request.finish() | |
95 return defer.succeed(None) | |
96 elif result is server.NOT_DONE_YET: | |
97 if request.finished: | |
98 return defer.succeed(None) | |
99 else: | |
100 return request.notifyFinish() | |
101 else: | |
102 raise ValueError("Unexpected return value: %r" % (result,)) | |
103 | |
104 | |
105 class DummyRequest(requesthelper.DummyRequest): | |
106 | |
107 def __init__(self, *args, **kwargs): | |
108 requesthelper.DummyRequest.__init__(self, *args, **kwargs) | |
109 self.requestHeaders = http_headers.Headers() | |
110 | |
111 | |
112 | |
113 class GetServiceAndNodeTest(unittest.TestCase): | |
114 """ | |
115 Tests for {gateway.getServiceAndNode}. | |
116 """ | |
117 | |
118 def test_basic(self): | |
119 """ | |
120 getServiceAndNode parses an XMPP URI with node parameter. | |
121 """ | |
122 uri = b'xmpp:pubsub.example.org?;node=test' | |
123 service, nodeIdentifier = gateway.getServiceAndNode(uri) | |
124 self.assertEqual(JID(u'pubsub.example.org'), service) | |
125 self.assertEqual(u'test', nodeIdentifier) | |
126 | |
127 | |
128 def test_schemeEmpty(self): | |
129 """ | |
130 If the URI scheme is empty, an exception is raised. | |
131 """ | |
132 uri = b'pubsub.example.org' | |
133 self.assertRaises(gateway.XMPPURIParseError, | |
134 gateway.getServiceAndNode, uri) | |
135 | |
136 | |
137 def test_schemeNotXMPP(self): | |
138 """ | |
139 If the URI scheme is not 'xmpp', an exception is raised. | |
140 """ | |
141 uri = b'mailto:test@example.org' | |
142 self.assertRaises(gateway.XMPPURIParseError, | |
143 gateway.getServiceAndNode, uri) | |
144 | |
145 | |
146 def test_authorityPresent(self): | |
147 """ | |
148 If the URI has an authority component, an exception is raised. | |
149 """ | |
150 uri = b'xmpp://pubsub.example.org/' | |
151 self.assertRaises(gateway.XMPPURIParseError, | |
152 gateway.getServiceAndNode, uri) | |
153 | |
154 | |
155 def test_queryEmpty(self): | |
156 """ | |
157 If there is no query component, the nodeIdentifier is empty. | |
158 """ | |
159 uri = b'xmpp:pubsub.example.org' | |
160 service, nodeIdentifier = gateway.getServiceAndNode(uri) | |
161 | |
162 self.assertEqual(JID(u'pubsub.example.org'), service) | |
163 self.assertEqual(u'', nodeIdentifier) | |
164 | |
165 | |
166 def test_jidInvalid(self): | |
167 """ | |
168 If the JID from the path component is invalid, an exception is raised. | |
169 """ | |
170 uri = b'xmpp:@@pubsub.example.org?;node=test' | |
171 self.assertRaises(gateway.XMPPURIParseError, | |
172 gateway.getServiceAndNode, uri) | |
173 | |
174 | |
175 def test_pathEmpty(self): | |
176 """ | |
177 If there is no path component, an exception is raised. | |
178 """ | |
179 uri = b'xmpp:?node=test' | |
180 self.assertRaises(gateway.XMPPURIParseError, | |
181 gateway.getServiceAndNode, uri) | |
182 | |
183 | |
184 def test_nodeAbsent(self): | |
185 """ | |
186 If the node parameter is missing, the nodeIdentifier is empty. | |
187 """ | |
188 uri = b'xmpp:pubsub.example.org?' | |
189 service, nodeIdentifier = gateway.getServiceAndNode(uri) | |
190 | |
191 self.assertEqual(JID(u'pubsub.example.org'), service) | |
192 self.assertEqual(u'', nodeIdentifier) | |
193 | |
194 | |
195 | |
196 class GetXMPPURITest(unittest.TestCase): | |
197 """ | |
198 Tests for L{gateway.getXMPPURITest}. | |
199 """ | |
200 | |
201 def test_basic(self): | |
202 uri = gateway.getXMPPURI(JID(u'pubsub.example.org'), u'test') | |
203 self.assertEqual('xmpp:pubsub.example.org?;node=test', uri) | |
204 | |
205 | |
206 class CreateResourceTest(unittest.TestCase): | |
207 """ | |
208 Tests for L{gateway.CreateResource}. | |
209 """ | |
210 | |
211 def setUp(self): | |
212 self.backend = BackendService(Storage()) | |
213 self.resource = gateway.CreateResource(self.backend, componentJID, | |
214 ownerJID) | |
215 | |
216 | |
217 def test_get(self): | |
218 """ | |
219 The method GET is not supported. | |
220 """ | |
221 request = DummyRequest([b'']) | |
222 self.assertRaises(error.UnsupportedMethod, | |
223 _render, self.resource, request) | |
224 | |
225 | |
226 def test_post(self): | |
227 """ | |
228 Upon a POST, a new node is created and the URI returned. | |
229 """ | |
230 request = DummyRequest([b'']) | |
231 request.method = 'POST' | |
232 | |
233 def gotNodes(nodeIdentifiers, uri): | |
234 service, nodeIdentifier = gateway.getServiceAndNode(uri) | |
235 self.assertIn(nodeIdentifier, nodeIdentifiers) | |
236 | |
237 def rendered(result): | |
238 self.assertEqual('application/json', | |
239 request.outgoingHeaders['content-type']) | |
240 payload = simplejson.loads(b''.join(request.written)) | |
241 self.assertIn('uri', payload) | |
242 d = self.backend.getNodes() | |
243 d.addCallback(gotNodes, payload['uri']) | |
244 return d | |
245 | |
246 d = _render(self.resource, request) | |
247 d.addCallback(rendered) | |
248 return d | |
249 | |
250 | |
251 | |
252 class DeleteResourceTest(unittest.TestCase): | |
253 """ | |
254 Tests for L{gateway.DeleteResource}. | |
255 """ | |
256 | |
257 def setUp(self): | |
258 self.backend = BackendService(Storage()) | |
259 self.resource = gateway.DeleteResource(self.backend, componentJID, | |
260 ownerJID) | |
261 | |
262 | |
263 def test_get(self): | |
264 """ | |
265 The method GET is not supported. | |
266 """ | |
267 request = DummyRequest([b'']) | |
268 self.assertRaises(error.UnsupportedMethod, | |
269 _render, self.resource, request) | |
270 | |
271 | |
272 def test_post(self): | |
273 """ | |
274 Upon a POST, a new node is created and the URI returned. | |
275 """ | |
276 request = DummyRequest([b'']) | |
277 request.method = b'POST' | |
278 | |
279 def rendered(result): | |
280 self.assertEqual(http.NO_CONTENT, request.responseCode) | |
281 | |
282 def nodeCreated(nodeIdentifier): | |
283 uri = gateway.getXMPPURI(componentJID, nodeIdentifier) | |
284 request.args[b'uri'] = [uri] | |
285 request.content = StringIO(b'') | |
286 | |
287 return _render(self.resource, request) | |
288 | |
289 d = self.backend.createNode(u'test', ownerJID) | |
290 d.addCallback(nodeCreated) | |
291 d.addCallback(rendered) | |
292 return d | |
293 | |
294 | |
295 def test_postWithRedirect(self): | |
296 """ | |
297 Upon a POST, a new node is created and the URI returned. | |
298 """ | |
299 request = DummyRequest([b'']) | |
300 request.method = b'POST' | |
301 otherNodeURI = b'xmpp:pubsub.example.org?node=other' | |
302 | |
303 def rendered(result): | |
304 self.assertEqual(http.NO_CONTENT, request.responseCode) | |
305 self.assertEqual(1, len(deletes)) | |
306 nodeIdentifier, owner, redirectURI = deletes[-1] | |
307 self.assertEqual(otherNodeURI, redirectURI) | |
308 | |
309 def nodeCreated(nodeIdentifier): | |
310 uri = gateway.getXMPPURI(componentJID, nodeIdentifier) | |
311 request.args[b'uri'] = [uri] | |
312 payload = {b'redirect_uri': otherNodeURI} | |
313 body = simplejson.dumps(payload) | |
314 request.content = StringIO(body) | |
315 return _render(self.resource, request) | |
316 | |
317 def deleteNode(nodeIdentifier, owner, redirectURI): | |
318 deletes.append((nodeIdentifier, owner, redirectURI)) | |
319 return defer.succeed(nodeIdentifier) | |
320 | |
321 deletes = [] | |
322 self.patch(self.backend, 'deleteNode', deleteNode) | |
323 d = self.backend.createNode(u'test', ownerJID) | |
324 d.addCallback(nodeCreated) | |
325 d.addCallback(rendered) | |
326 return d | |
327 | |
328 | |
329 def test_postUnknownNode(self): | |
330 """ | |
331 If the node to be deleted is unknown, 404 Not Found is returned. | |
332 """ | |
333 request = DummyRequest([b'']) | |
334 request.method = b'POST' | |
335 | |
336 def rendered(result): | |
337 self.assertEqual(http.NOT_FOUND, request.responseCode) | |
338 | |
339 uri = gateway.getXMPPURI(componentJID, u'unknown') | |
340 request.args[b'uri'] = [uri] | |
341 request.content = StringIO(b'') | |
342 | |
343 d = _render(self.resource, request) | |
344 d.addCallback(rendered) | |
345 return d | |
346 | |
347 | |
348 def test_postMalformedXMPPURI(self): | |
349 """ | |
350 If the XMPP URI is malformed, Bad Request is returned. | |
351 """ | |
352 request = DummyRequest([b'']) | |
353 request.method = b'POST' | |
354 | |
355 def rendered(result): | |
356 self.assertEqual(http.BAD_REQUEST, request.responseCode) | |
357 | |
358 uri = 'xmpp:@@@@' | |
359 request.args[b'uri'] = [uri] | |
360 request.content = StringIO(b'') | |
361 | |
362 d = _render(self.resource, request) | |
363 d.addCallback(rendered) | |
364 return d | |
365 | |
366 | |
367 def test_postURIMissing(self): | |
368 """ | |
369 If no URI is passed, 400 Bad Request is returned. | |
370 """ | |
371 request = DummyRequest([b'']) | |
372 request.method = b'POST' | |
373 | |
374 def rendered(result): | |
375 self.assertEqual(http.BAD_REQUEST, request.responseCode) | |
376 | |
377 request.content = StringIO(b'') | |
378 | |
379 d = _render(self.resource, request) | |
380 d.addCallback(rendered) | |
381 return d | |
382 | |
383 | |
384 | |
385 class CallbackResourceTest(unittest.TestCase): | |
386 """ | |
387 Tests for L{gateway.CallbackResource}. | |
388 """ | |
389 | |
390 def setUp(self): | |
391 self.callbackEvents = [] | |
392 self.resource = gateway.CallbackResource(self._callback) | |
393 | |
394 | |
395 def _callback(self, payload, headers): | |
396 self.callbackEvents.append((payload, headers)) | |
397 | |
398 | |
399 def test_get(self): | |
400 """ | |
401 The method GET is not supported. | |
402 """ | |
403 request = DummyRequest([b'']) | |
404 self.assertRaises(error.UnsupportedMethod, | |
405 _render, self.resource, request) | |
406 | |
407 | |
408 def test_post(self): | |
409 """ | |
410 The body posted is passed to the callback. | |
411 """ | |
412 request = DummyRequest([b'']) | |
413 request.method = 'POST' | |
414 request.content = StringIO(b'<root><child/></root>') | |
415 | |
416 def rendered(result): | |
417 self.assertEqual(1, len(self.callbackEvents)) | |
418 payload, headers = self.callbackEvents[-1] | |
419 self.assertEqual('root', payload.name) | |
420 | |
421 self.assertEqual(http.NO_CONTENT, request.responseCode) | |
422 self.assertFalse(b''.join(request.written)) | |
423 | |
424 d = _render(self.resource, request) | |
425 d.addCallback(rendered) | |
426 return d | |
427 | |
428 | |
429 def test_postEvent(self): | |
430 """ | |
431 If the Event header is set, the payload is empty and the header passed. | |
432 """ | |
433 request = DummyRequest([b'']) | |
434 request.method = 'POST' | |
435 request.requestHeaders.addRawHeader(b'Event', b'DELETE') | |
436 request.content = StringIO(b'') | |
437 | |
438 def rendered(result): | |
439 self.assertEqual(1, len(self.callbackEvents)) | |
440 payload, headers = self.callbackEvents[-1] | |
441 self.assertIdentical(None, payload) | |
442 self.assertEqual(['DELETE'], headers.getRawHeaders(b'Event')) | |
443 self.assertFalse(b''.join(request.written)) | |
444 | |
445 d = _render(self.resource, request) | |
446 d.addCallback(rendered) | |
447 return d | |
448 | |
449 | |
450 | |
451 class GatewayTest(unittest.TestCase): | |
452 timeout = 2 | |
453 | |
454 def setUp(self): | |
455 self.client = gateway.GatewayClient(baseURI) | |
456 self.client.startService() | |
457 self.addCleanup(self.client.stopService) | |
458 | |
459 def trapConnectionRefused(failure): | |
460 from twisted.internet.error import ConnectionRefusedError | |
461 failure.trap(ConnectionRefusedError) | |
462 raise unittest.SkipTest("Gateway to test against is not available") | |
463 | |
464 def trapNotFound(failure): | |
465 from twisted.web.error import Error | |
466 failure.trap(Error) | |
467 | |
468 d = self.client.ping() | |
469 d.addErrback(trapConnectionRefused) | |
470 d.addErrback(trapNotFound) | |
471 return d | |
472 | |
473 | |
474 def tearDown(self): | |
475 return self.client.stopService() | |
476 | |
477 | |
478 def test_create(self): | |
479 | |
480 def cb(response): | |
481 self.assertIn('uri', response) | |
482 | |
483 d = self.client.create() | |
484 d.addCallback(cb) | |
485 return d | |
486 | |
487 def test_publish(self): | |
488 | |
489 def cb(response): | |
490 self.assertIn('uri', response) | |
491 | |
492 d = self.client.publish(TEST_ENTRY) | |
493 d.addCallback(cb) | |
494 return d | |
495 | |
496 def test_publishExistingNode(self): | |
497 | |
498 def cb2(response, xmppURI): | |
499 self.assertEquals(xmppURI, response['uri']) | |
500 | |
501 def cb1(response): | |
502 xmppURI = response['uri'] | |
503 d = self.client.publish(TEST_ENTRY, xmppURI) | |
504 d.addCallback(cb2, xmppURI) | |
505 return d | |
506 | |
507 d = self.client.create() | |
508 d.addCallback(cb1) | |
509 return d | |
510 | |
511 def test_publishNonExisting(self): | |
512 def cb(err): | |
513 self.assertEqual('404', err.status) | |
514 | |
515 d = self.client.publish(TEST_ENTRY, 'xmpp:%s?node=test' % component) | |
516 self.assertFailure(d, error.Error) | |
517 d.addCallback(cb) | |
518 return d | |
519 | |
520 def test_delete(self): | |
521 def cb(response): | |
522 xmppURI = response['uri'] | |
523 d = self.client.delete(xmppURI) | |
524 return d | |
525 | |
526 d = self.client.create() | |
527 d.addCallback(cb) | |
528 return d | |
529 | |
530 def test_deleteWithRedirect(self): | |
531 def cb(response): | |
532 xmppURI = response['uri'] | |
533 redirectURI = 'xmpp:%s?node=test' % component | |
534 d = self.client.delete(xmppURI, redirectURI) | |
535 return d | |
536 | |
537 d = self.client.create() | |
538 d.addCallback(cb) | |
539 return d | |
540 | |
541 def test_deleteNotification(self): | |
542 def onNotification(data, headers): | |
543 try: | |
544 self.assertTrue(headers.hasHeader('Event')) | |
545 self.assertEquals(['DELETED'], headers.getRawHeaders('Event')) | |
546 self.assertFalse(headers.hasHeader('Link')) | |
547 except: | |
548 self.client.deferred.errback() | |
549 else: | |
550 self.client.deferred.callback(None) | |
551 | |
552 def cb(response): | |
553 xmppURI = response['uri'] | |
554 d = self.client.subscribe(xmppURI) | |
555 d.addCallback(lambda _: xmppURI) | |
556 return d | |
557 | |
558 def cb2(xmppURI): | |
559 d = self.client.delete(xmppURI) | |
560 return d | |
561 | |
562 self.client.callback = onNotification | |
563 self.client.deferred = defer.Deferred() | |
564 d = self.client.create() | |
565 d.addCallback(cb) | |
566 d.addCallback(cb2) | |
567 return defer.gatherResults([d, self.client.deferred]) | |
568 | |
569 def test_deleteNotificationWithRedirect(self): | |
570 redirectURI = 'xmpp:%s?node=test' % component | |
571 | |
572 def onNotification(data, headers): | |
573 try: | |
574 self.assertTrue(headers.hasHeader('Event')) | |
575 self.assertEquals(['DELETED'], headers.getRawHeaders('Event')) | |
576 self.assertEquals(['<%s>; rel=alternate' % redirectURI], | |
577 headers.getRawHeaders('Link')) | |
578 except: | |
579 self.client.deferred.errback() | |
580 else: | |
581 self.client.deferred.callback(None) | |
582 | |
583 def cb(response): | |
584 xmppURI = response['uri'] | |
585 d = self.client.subscribe(xmppURI) | |
586 d.addCallback(lambda _: xmppURI) | |
587 return d | |
588 | |
589 def cb2(xmppURI): | |
590 d = self.client.delete(xmppURI, redirectURI) | |
591 return d | |
592 | |
593 self.client.callback = onNotification | |
594 self.client.deferred = defer.Deferred() | |
595 d = self.client.create() | |
596 d.addCallback(cb) | |
597 d.addCallback(cb2) | |
598 return defer.gatherResults([d, self.client.deferred]) | |
599 | |
600 def test_list(self): | |
601 d = self.client.listNodes() | |
602 return d | |
603 | |
604 def test_subscribe(self): | |
605 def cb(response): | |
606 xmppURI = response['uri'] | |
607 d = self.client.subscribe(xmppURI) | |
608 return d | |
609 | |
610 d = self.client.create() | |
611 d.addCallback(cb) | |
612 return d | |
613 | |
614 def test_subscribeGetNotification(self): | |
615 | |
616 def onNotification(data, headers): | |
617 self.client.deferred.callback(None) | |
618 | |
619 def cb(response): | |
620 xmppURI = response['uri'] | |
621 d = self.client.subscribe(xmppURI) | |
622 d.addCallback(lambda _: xmppURI) | |
623 return d | |
624 | |
625 def cb2(xmppURI): | |
626 d = self.client.publish(TEST_ENTRY, xmppURI) | |
627 return d | |
628 | |
629 | |
630 self.client.callback = onNotification | |
631 self.client.deferred = defer.Deferred() | |
632 d = self.client.create() | |
633 d.addCallback(cb) | |
634 d.addCallback(cb2) | |
635 return defer.gatherResults([d, self.client.deferred]) | |
636 | |
637 | |
638 def test_subscribeTwiceGetNotification(self): | |
639 | |
640 def onNotification1(data, headers): | |
641 d = client1.stopService() | |
642 d.chainDeferred(client1.deferred) | |
643 | |
644 def onNotification2(data, headers): | |
645 d = client2.stopService() | |
646 d.chainDeferred(client2.deferred) | |
647 | |
648 def cb(response): | |
649 xmppURI = response['uri'] | |
650 d = client1.subscribe(xmppURI) | |
651 d.addCallback(lambda _: xmppURI) | |
652 return d | |
653 | |
654 def cb2(xmppURI): | |
655 d = client2.subscribe(xmppURI) | |
656 d.addCallback(lambda _: xmppURI) | |
657 return d | |
658 | |
659 def cb3(xmppURI): | |
660 d = self.client.publish(TEST_ENTRY, xmppURI) | |
661 return d | |
662 | |
663 | |
664 client1 = gateway.GatewayClient(baseURI, callbackPort=8088) | |
665 client1.startService() | |
666 client1.callback = onNotification1 | |
667 client1.deferred = defer.Deferred() | |
668 client2 = gateway.GatewayClient(baseURI, callbackPort=8089) | |
669 client2.startService() | |
670 client2.callback = onNotification2 | |
671 client2.deferred = defer.Deferred() | |
672 | |
673 d = self.client.create() | |
674 d.addCallback(cb) | |
675 d.addCallback(cb2) | |
676 d.addCallback(cb3) | |
677 dl = defer.gatherResults([d, client1.deferred, client2.deferred]) | |
678 return dl | |
679 | |
680 | |
681 def test_subscribeGetDelayedNotification(self): | |
682 | |
683 def onNotification(data, headers): | |
684 self.client.deferred.callback(None) | |
685 | |
686 def cb(response): | |
687 xmppURI = response['uri'] | |
688 self.assertNot(self.client.deferred.called) | |
689 d = self.client.publish(TEST_ENTRY, xmppURI) | |
690 d.addCallback(lambda _: xmppURI) | |
691 return d | |
692 | |
693 def cb2(xmppURI): | |
694 d = self.client.subscribe(xmppURI) | |
695 return d | |
696 | |
697 | |
698 self.client.callback = onNotification | |
699 self.client.deferred = defer.Deferred() | |
700 d = self.client.create() | |
701 d.addCallback(cb) | |
702 d.addCallback(cb2) | |
703 return defer.gatherResults([d, self.client.deferred]) | |
704 | |
705 def test_subscribeGetDelayedNotification2(self): | |
706 """ | |
707 Test that subscribing as second results in a notification being sent. | |
708 """ | |
709 | |
710 def onNotification1(data, headers): | |
711 client1.deferred.callback(None) | |
712 client1.stopService() | |
713 | |
714 def onNotification2(data, headers): | |
715 client2.deferred.callback(None) | |
716 client2.stopService() | |
717 | |
718 def cb(response): | |
719 xmppURI = response['uri'] | |
720 self.assertNot(client1.deferred.called) | |
721 self.assertNot(client2.deferred.called) | |
722 d = self.client.publish(TEST_ENTRY, xmppURI) | |
723 d.addCallback(lambda _: xmppURI) | |
724 return d | |
725 | |
726 def cb2(xmppURI): | |
727 d = client1.subscribe(xmppURI) | |
728 d.addCallback(lambda _: xmppURI) | |
729 return d | |
730 | |
731 def cb3(xmppURI): | |
732 d = client2.subscribe(xmppURI) | |
733 return d | |
734 | |
735 client1 = gateway.GatewayClient(baseURI, callbackPort=8088) | |
736 client1.startService() | |
737 client1.callback = onNotification1 | |
738 client1.deferred = defer.Deferred() | |
739 client2 = gateway.GatewayClient(baseURI, callbackPort=8089) | |
740 client2.startService() | |
741 client2.callback = onNotification2 | |
742 client2.deferred = defer.Deferred() | |
743 | |
744 | |
745 d = self.client.create() | |
746 d.addCallback(cb) | |
747 d.addCallback(cb2) | |
748 d.addCallback(cb3) | |
749 dl = defer.gatherResults([d, client1.deferred, client2.deferred]) | |
750 return dl | |
751 | |
752 | |
753 def test_subscribeNonExisting(self): | |
754 def cb(err): | |
755 self.assertEqual('403', err.status) | |
756 | |
757 d = self.client.subscribe('xmpp:%s?node=test' % component) | |
758 self.assertFailure(d, error.Error) | |
759 d.addCallback(cb) | |
760 return d | |
761 | |
762 | |
763 def test_subscribeRootGetNotification(self): | |
764 | |
765 def clean(rootNode): | |
766 return self.client.unsubscribe(rootNode) | |
767 | |
768 def onNotification(data, headers): | |
769 self.client.deferred.callback(None) | |
770 | |
771 def cb(response): | |
772 xmppURI = response['uri'] | |
773 jid, nodeIdentifier = gateway.getServiceAndNode(xmppURI) | |
774 rootNode = gateway.getXMPPURI(jid, '') | |
775 | |
776 d = self.client.subscribe(rootNode) | |
777 d.addCallback(lambda _: self.addCleanup(clean, rootNode)) | |
778 d.addCallback(lambda _: xmppURI) | |
779 return d | |
780 | |
781 def cb2(xmppURI): | |
782 return self.client.publish(TEST_ENTRY, xmppURI) | |
783 | |
784 | |
785 self.client.callback = onNotification | |
786 self.client.deferred = defer.Deferred() | |
787 d = self.client.create() | |
788 d.addCallback(cb) | |
789 d.addCallback(cb2) | |
790 return defer.gatherResults([d, self.client.deferred]) | |
791 | |
792 | |
793 def test_unsubscribeNonExisting(self): | |
794 def cb(err): | |
795 self.assertEqual('403', err.status) | |
796 | |
797 d = self.client.unsubscribe('xmpp:%s?node=test' % component) | |
798 self.assertFailure(d, error.Error) | |
799 d.addCallback(cb) | |
800 return d | |
801 | |
802 | |
803 def test_items(self): | |
804 def cb(response): | |
805 xmppURI = response['uri'] | |
806 d = self.client.items(xmppURI) | |
807 return d | |
808 | |
809 d = self.client.publish(TEST_ENTRY) | |
810 d.addCallback(cb) | |
811 return d | |
812 | |
813 | |
814 def test_itemsMaxItems(self): | |
815 def cb(response): | |
816 xmppURI = response['uri'] | |
817 d = self.client.items(xmppURI, 2) | |
818 return d | |
819 | |
820 d = self.client.publish(TEST_ENTRY) | |
821 d.addCallback(cb) | |
822 return d |