Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / words / test / test_service.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Tests for L{twisted.words.service}.
6 """
7
8 import time
9
10 from twisted.trial import unittest
11 from twisted.test import proto_helpers
12
13 from twisted.cred import portal, credentials, checkers
14 from twisted.words import ewords, service
15 from twisted.words.protocols import irc
16 from twisted.spread import pb
17 from twisted.internet.defer import Deferred, DeferredList, maybeDeferred, succeed
18 from twisted.internet.defer import deferredGenerator as dG, waitForDeferred as wFD
19 from twisted.internet import address, reactor
20
21 class RealmTestCase(unittest.TestCase):
22     def _entityCreationTest(self, kind):
23         # Kind is "user" or "group"
24         realm = service.InMemoryWordsRealm("realmname")
25
26         name = u'test' + kind.lower()
27         create = getattr(realm, 'create' + kind.title())
28         get = getattr(realm, 'get' + kind.title())
29         flag = 'create' + kind.title() + 'OnRequest'
30         dupExc = getattr(ewords, 'Duplicate' + kind.title())
31         noSuchExc = getattr(ewords, 'NoSuch' + kind.title())
32
33         # Creating should succeed
34         d = wFD(create(name))
35         yield d
36         p = d.getResult()
37         self.assertEqual(p.name, name)
38
39         # Creating the same user again should not
40         d = wFD(create(name))
41         yield d
42         self.assertRaises(dupExc, d.getResult)
43
44         # Getting a non-existent user should succeed if createUserOnRequest is True
45         setattr(realm, flag, True)
46         d = wFD(get(u"new" + kind.lower()))
47         yield d
48         p = d.getResult()
49         self.assertEqual(p.name, "new" + kind.lower())
50
51         # Getting that user again should return the same object
52         d = wFD(get(u"new" + kind.lower()))
53         yield d
54         newp = d.getResult()
55         self.assertIdentical(p, newp)
56
57         # Getting a non-existent user should fail if createUserOnRequest is False
58         setattr(realm, flag, False)
59         d = wFD(get(u"another" + kind.lower()))
60         yield d
61         self.assertRaises(noSuchExc, d.getResult)
62     _entityCreationTest = dG(_entityCreationTest)
63
64
65     def testUserCreation(self):
66         return self._entityCreationTest("User")
67
68
69     def testGroupCreation(self):
70         return self._entityCreationTest("Group")
71
72
73     def testUserRetrieval(self):
74         realm = service.InMemoryWordsRealm("realmname")
75
76         # Make a user to play around with
77         d = wFD(realm.createUser(u"testuser"))
78         yield d
79         user = d.getResult()
80
81         # Make sure getting the user returns the same object
82         d = wFD(realm.getUser(u"testuser"))
83         yield d
84         retrieved = d.getResult()
85         self.assertIdentical(user, retrieved)
86
87         # Make sure looking up the user also returns the same object
88         d = wFD(realm.lookupUser(u"testuser"))
89         yield d
90         lookedUp = d.getResult()
91         self.assertIdentical(retrieved, lookedUp)
92
93         # Make sure looking up a user who does not exist fails
94         d = wFD(realm.lookupUser(u"nosuchuser"))
95         yield d
96         self.assertRaises(ewords.NoSuchUser, d.getResult)
97     testUserRetrieval = dG(testUserRetrieval)
98
99
100     def testUserAddition(self):
101         realm = service.InMemoryWordsRealm("realmname")
102
103         # Create and manually add a user to the realm
104         p = service.User("testuser")
105         d = wFD(realm.addUser(p))
106         yield d
107         user = d.getResult()
108         self.assertIdentical(p, user)
109
110         # Make sure getting that user returns the same object
111         d = wFD(realm.getUser(u"testuser"))
112         yield d
113         retrieved = d.getResult()
114         self.assertIdentical(user, retrieved)
115
116         # Make sure looking up that user returns the same object
117         d = wFD(realm.lookupUser(u"testuser"))
118         yield d
119         lookedUp = d.getResult()
120         self.assertIdentical(retrieved, lookedUp)
121     testUserAddition = dG(testUserAddition)
122
123
124     def testGroupRetrieval(self):
125         realm = service.InMemoryWordsRealm("realmname")
126
127         d = wFD(realm.createGroup(u"testgroup"))
128         yield d
129         group = d.getResult()
130
131         d = wFD(realm.getGroup(u"testgroup"))
132         yield d
133         retrieved = d.getResult()
134
135         self.assertIdentical(group, retrieved)
136
137         d = wFD(realm.getGroup(u"nosuchgroup"))
138         yield d
139         self.assertRaises(ewords.NoSuchGroup, d.getResult)
140     testGroupRetrieval = dG(testGroupRetrieval)
141
142
143     def testGroupAddition(self):
144         realm = service.InMemoryWordsRealm("realmname")
145
146         p = service.Group("testgroup")
147         d = wFD(realm.addGroup(p))
148         yield d
149         d.getResult()
150
151         d = wFD(realm.getGroup(u"testGroup"))
152         yield d
153         group = d.getResult()
154
155         self.assertIdentical(p, group)
156     testGroupAddition = dG(testGroupAddition)
157
158
159     def testGroupUsernameCollision(self):
160         """
161         Try creating a group with the same name as an existing user and
162         assert that it succeeds, since users and groups should not be in the
163         same namespace and collisions should be impossible.
164         """
165         realm = service.InMemoryWordsRealm("realmname")
166
167         d = wFD(realm.createUser(u"test"))
168         yield d
169         user = d.getResult()
170
171         d = wFD(realm.createGroup(u"test"))
172         yield d
173         group = d.getResult()
174     testGroupUsernameCollision = dG(testGroupUsernameCollision)
175
176
177     def testEnumeration(self):
178         realm = service.InMemoryWordsRealm("realmname")
179         d = wFD(realm.createGroup(u"groupone"))
180         yield d
181         d.getResult()
182
183         d = wFD(realm.createGroup(u"grouptwo"))
184         yield d
185         d.getResult()
186
187         groups = wFD(realm.itergroups())
188         yield groups
189         groups = groups.getResult()
190
191         n = [g.name for g in groups]
192         n.sort()
193         self.assertEqual(n, ["groupone", "grouptwo"])
194     testEnumeration = dG(testEnumeration)
195
196
197 class TestGroup(object):
198     def __init__(self, name, size, topic):
199         self.name = name
200         self.size = lambda: size
201         self.meta = {'topic': topic}
202
203
204 class TestUser(object):
205     def __init__(self, name, groups, signOn, lastMessage):
206         self.name = name
207         self.itergroups = lambda: iter([TestGroup(g, 3, 'Hello') for g in groups])
208         self.signOn = signOn
209         self.lastMessage = lastMessage
210
211
212 class TestPortal(object):
213     def __init__(self):
214         self.logins = []
215
216
217     def login(self, credentials, mind, *interfaces):
218         d = Deferred()
219         self.logins.append((credentials, mind, interfaces, d))
220         return d
221
222
223 class TestCaseUserAgg(object):
224     def __init__(self, user, realm, factory, address=address.IPv4Address('TCP', '127.0.0.1', 54321)):
225         self.user = user
226         self.transport = proto_helpers.StringTransportWithDisconnection()
227         self.protocol = factory.buildProtocol(address)
228         self.transport.protocol = self.protocol
229         self.user.mind = self.protocol
230         self.protocol.makeConnection(self.transport)
231
232
233     def write(self, stuff):
234         if isinstance(stuff, unicode):
235             stuff = stuff.encode('utf-8')
236         self.protocol.dataReceived(stuff)
237
238
239 class IRCProtocolTestCase(unittest.TestCase):
240     STATIC_USERS = [
241         u'useruser', u'otheruser', u'someguy', u'firstuser', u'username',
242         u'userone', u'usertwo', u'userthree', u'someuser']
243
244
245     def setUp(self):
246         self.realm = service.InMemoryWordsRealm("realmname")
247         self.checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
248         self.portal = portal.Portal(self.realm, [self.checker])
249         self.factory = service.IRCFactory(self.realm, self.portal)
250
251         c = []
252         for nick in self.STATIC_USERS:
253             c.append(self.realm.createUser(nick))
254             self.checker.addUser(nick.encode('ascii'), nick + "_password")
255         return DeferredList(c)
256
257
258     def _assertGreeting(self, user):
259         """
260         The user has been greeted with the four messages that are (usually)
261         considered to start an IRC session.
262         
263         Asserts that the required responses were received.
264         """
265         # Make sure we get 1-4 at least
266         response = self._response(user)
267         expected = [irc.RPL_WELCOME, irc.RPL_YOURHOST, irc.RPL_CREATED,
268                     irc.RPL_MYINFO]
269         for (prefix, command, args) in response:
270             if command in expected:
271                 expected.remove(command)
272         self.failIf(expected, "Missing responses for %r" % (expected,))
273
274
275     def _login(self, user, nick, password=None):
276         if password is None:
277             password = nick + "_password"
278         user.write('PASS %s\r\n' % (password,))
279         user.write('NICK %s extrainfo\r\n' % (nick,))
280
281
282     def _loggedInUser(self, name):
283         d = wFD(self.realm.lookupUser(name))
284         yield d
285         user = d.getResult()
286         agg = TestCaseUserAgg(user, self.realm, self.factory)
287         self._login(agg, name)
288         yield agg
289     _loggedInUser = dG(_loggedInUser)
290
291
292     def _response(self, user, messageType=None):
293         """
294         Extracts the user's response, and returns a list of parsed lines.
295         If messageType is defined, only messages of that type will be returned.
296         """
297         response = user.transport.value().splitlines()
298         user.transport.clear()
299         result = []
300         for message in map(irc.parsemsg, response):
301             if messageType is None or message[1] == messageType:
302                 result.append(message)
303         return result
304
305
306     def testPASSLogin(self):
307         user = wFD(self._loggedInUser(u'firstuser'))
308         yield user
309         user = user.getResult()
310         self._assertGreeting(user)
311     testPASSLogin = dG(testPASSLogin)
312
313
314     def test_nickServLogin(self):
315         """
316         Sending NICK without PASS will prompt the user for their password.
317         When the user sends their password to NickServ, it will respond with a
318         Greeting.
319         """
320         firstuser = wFD(self.realm.lookupUser(u'firstuser'))
321         yield firstuser
322         firstuser = firstuser.getResult()
323
324         user = TestCaseUserAgg(firstuser, self.realm, self.factory)
325         user.write('NICK firstuser extrainfo\r\n')
326         response = self._response(user, 'PRIVMSG')
327         self.assertEqual(len(response), 1)
328         self.assertEqual(response[0][0], service.NICKSERV)
329         self.assertEqual(response[0][1], 'PRIVMSG')
330         self.assertEqual(response[0][2], ['firstuser', 'Password?'])
331         user.transport.clear()
332
333         user.write('PRIVMSG nickserv firstuser_password\r\n')
334         self._assertGreeting(user)
335     test_nickServLogin = dG(test_nickServLogin)
336
337
338     def testFailedLogin(self):
339         firstuser = wFD(self.realm.lookupUser(u'firstuser'))
340         yield firstuser
341         firstuser = firstuser.getResult()
342
343         user = TestCaseUserAgg(firstuser, self.realm, self.factory)
344         self._login(user, "firstuser", "wrongpass")
345         response = self._response(user, "PRIVMSG")
346         self.assertEqual(len(response), 1)
347         self.assertEqual(response[0][2], ['firstuser', 'Login failed.  Goodbye.'])
348     testFailedLogin = dG(testFailedLogin)
349
350
351     def testLogout(self):
352         logout = []
353         firstuser = wFD(self.realm.lookupUser(u'firstuser'))
354         yield firstuser
355         firstuser = firstuser.getResult()
356
357         user = TestCaseUserAgg(firstuser, self.realm, self.factory)
358         self._login(user, "firstuser")
359         user.protocol.logout = lambda: logout.append(True)
360         user.write('QUIT\r\n')
361         self.assertEqual(logout, [True])
362     testLogout = dG(testLogout)
363
364
365     def testJoin(self):
366         firstuser = wFD(self.realm.lookupUser(u'firstuser'))
367         yield firstuser
368         firstuser = firstuser.getResult()
369
370         somechannel = wFD(self.realm.createGroup(u"somechannel"))
371         yield somechannel
372         somechannel = somechannel.getResult()
373
374         somechannel.meta['topic'] = 'some random topic'
375
376         # Bring in one user, make sure he gets into the channel sanely
377         user = TestCaseUserAgg(firstuser, self.realm, self.factory)
378         self._login(user, "firstuser")
379         user.transport.clear()
380         user.write('JOIN #somechannel\r\n')
381
382         response = self._response(user)
383         self.assertEqual(len(response), 5)
384
385         # Join message
386         self.assertEqual(response[0][0], 'firstuser!firstuser@realmname')
387         self.assertEqual(response[0][1], 'JOIN')
388         self.assertEqual(response[0][2], ['#somechannel'])
389
390         # User list
391         self.assertEqual(response[1][1], '353')
392         self.assertEqual(response[2][1], '366')
393
394         # Topic (or lack thereof, as the case may be)
395         self.assertEqual(response[3][1], '332')
396         self.assertEqual(response[4][1], '333')
397
398
399         # Hook up another client!  It is a CHAT SYSTEM!!!!!!!
400         other = wFD(self._loggedInUser(u'otheruser'))
401         yield other
402         other = other.getResult()
403
404         other.transport.clear()
405         user.transport.clear()
406         other.write('JOIN #somechannel\r\n')
407
408         # At this point, both users should be in the channel
409         response = self._response(other)
410
411         event = self._response(user)
412         self.assertEqual(len(event), 1)
413         self.assertEqual(event[0][0], 'otheruser!otheruser@realmname')
414         self.assertEqual(event[0][1], 'JOIN')
415         self.assertEqual(event[0][2], ['#somechannel'])
416
417         self.assertEqual(response[1][0], 'realmname')
418         self.assertEqual(response[1][1], '353')
419         self.assertEqual(response[1][2], ['otheruser', '=', '#somechannel', 'firstuser otheruser'])
420     testJoin = dG(testJoin)
421
422
423     def test_joinTopicless(self):
424         """
425         When a user joins a group without a topic, no topic information is
426         sent to that user.
427         """
428         firstuser = wFD(self.realm.lookupUser(u'firstuser'))
429         yield firstuser
430         firstuser = firstuser.getResult()
431
432         somechannel = wFD(self.realm.createGroup(u"somechannel"))
433         yield somechannel
434         somechannel = somechannel.getResult()
435
436         # Bring in one user, make sure he gets into the channel sanely
437         user = TestCaseUserAgg(firstuser, self.realm, self.factory)
438         self._login(user, "firstuser")
439         user.transport.clear()
440         user.write('JOIN #somechannel\r\n')
441
442         response = self._response(user)
443         responseCodes = [r[1] for r in response]
444         self.assertNotIn('332', responseCodes)
445         self.assertNotIn('333', responseCodes)
446     test_joinTopicless = dG(test_joinTopicless)
447
448
449     def testLeave(self):
450         user = wFD(self._loggedInUser(u'useruser'))
451         yield user
452         user = user.getResult()
453
454         somechannel = wFD(self.realm.createGroup(u"somechannel"))
455         yield somechannel
456         somechannel = somechannel.getResult()
457
458         user.write('JOIN #somechannel\r\n')
459         user.transport.clear()
460
461         other = wFD(self._loggedInUser(u'otheruser'))
462         yield other
463         other = other.getResult()
464
465         other.write('JOIN #somechannel\r\n')
466
467         user.transport.clear()
468         other.transport.clear()
469
470         user.write('PART #somechannel\r\n')
471
472         response = self._response(user)
473         event = self._response(other)
474
475         self.assertEqual(len(response), 1)
476         self.assertEqual(response[0][0], 'useruser!useruser@realmname')
477         self.assertEqual(response[0][1], 'PART')
478         self.assertEqual(response[0][2], ['#somechannel', 'leaving'])
479         self.assertEqual(response, event)
480
481         # Now again, with a part message
482         user.write('JOIN #somechannel\r\n')
483
484         user.transport.clear()
485         other.transport.clear()
486
487         user.write('PART #somechannel :goodbye stupidheads\r\n')
488
489         response = self._response(user)
490         event = self._response(other)
491
492         self.assertEqual(len(response), 1)
493         self.assertEqual(response[0][0], 'useruser!useruser@realmname')
494         self.assertEqual(response[0][1], 'PART')
495         self.assertEqual(response[0][2], ['#somechannel', 'goodbye stupidheads'])
496         self.assertEqual(response, event)
497     testLeave = dG(testLeave)
498
499
500     def testGetTopic(self):
501         user = wFD(self._loggedInUser(u'useruser'))
502         yield user
503         user = user.getResult()
504
505         group = service.Group("somechannel")
506         group.meta["topic"] = "This is a test topic."
507         group.meta["topic_author"] = "some_fellow"
508         group.meta["topic_date"] = 77777777
509
510         add = wFD(self.realm.addGroup(group))
511         yield add
512         add.getResult()
513
514         user.transport.clear()
515         user.write("JOIN #somechannel\r\n")
516
517         response = self._response(user)
518
519         self.assertEqual(response[3][0], 'realmname')
520         self.assertEqual(response[3][1], '332')
521
522         # XXX Sigh.  irc.parsemsg() is not as correct as one might hope.
523         self.assertEqual(response[3][2], ['useruser', '#somechannel', 'This is a test topic.'])
524         self.assertEqual(response[4][1], '333')
525         self.assertEqual(response[4][2], ['useruser', '#somechannel', 'some_fellow', '77777777'])
526
527         user.transport.clear()
528
529         user.write('TOPIC #somechannel\r\n')
530
531         response = self._response(user)
532
533         self.assertEqual(response[0][1], '332')
534         self.assertEqual(response[0][2], ['useruser', '#somechannel', 'This is a test topic.'])
535         self.assertEqual(response[1][1], '333')
536         self.assertEqual(response[1][2], ['useruser', '#somechannel', 'some_fellow', '77777777'])
537     testGetTopic = dG(testGetTopic)
538
539
540     def testSetTopic(self):
541         user = wFD(self._loggedInUser(u'useruser'))
542         yield user
543         user = user.getResult()
544
545         add = wFD(self.realm.createGroup(u"somechannel"))
546         yield add
547         somechannel = add.getResult()
548
549         user.write("JOIN #somechannel\r\n")
550
551         other = wFD(self._loggedInUser(u'otheruser'))
552         yield other
553         other = other.getResult()
554
555         other.write("JOIN #somechannel\r\n")
556
557         user.transport.clear()
558         other.transport.clear()
559
560         other.write('TOPIC #somechannel :This is the new topic.\r\n')
561
562         response = self._response(other)
563         event = self._response(user)
564
565         self.assertEqual(response, event)
566
567         self.assertEqual(response[0][0], 'otheruser!otheruser@realmname')
568         self.assertEqual(response[0][1], 'TOPIC')
569         self.assertEqual(response[0][2], ['#somechannel', 'This is the new topic.'])
570
571         other.transport.clear()
572
573         somechannel.meta['topic_date'] = 12345
574         other.write('TOPIC #somechannel\r\n')
575
576         response = self._response(other)
577         self.assertEqual(response[0][1], '332')
578         self.assertEqual(response[0][2], ['otheruser', '#somechannel', 'This is the new topic.'])
579         self.assertEqual(response[1][1], '333')
580         self.assertEqual(response[1][2], ['otheruser', '#somechannel', 'otheruser', '12345'])
581
582         other.transport.clear()
583         other.write('TOPIC #asdlkjasd\r\n')
584
585         response = self._response(other)
586         self.assertEqual(response[0][1], '403')
587     testSetTopic = dG(testSetTopic)
588
589
590     def testGroupMessage(self):
591         user = wFD(self._loggedInUser(u'useruser'))
592         yield user
593         user = user.getResult()
594
595         add = wFD(self.realm.createGroup(u"somechannel"))
596         yield add
597         somechannel = add.getResult()
598
599         user.write("JOIN #somechannel\r\n")
600
601         other = wFD(self._loggedInUser(u'otheruser'))
602         yield other
603         other = other.getResult()
604
605         other.write("JOIN #somechannel\r\n")
606
607         user.transport.clear()
608         other.transport.clear()
609
610         user.write('PRIVMSG #somechannel :Hello, world.\r\n')
611
612         response = self._response(user)
613         event = self._response(other)
614
615         self.failIf(response)
616         self.assertEqual(len(event), 1)
617         self.assertEqual(event[0][0], 'useruser!useruser@realmname')
618         self.assertEqual(event[0][1], 'PRIVMSG', -1)
619         self.assertEqual(event[0][2], ['#somechannel', 'Hello, world.'])
620     testGroupMessage = dG(testGroupMessage)
621
622
623     def testPrivateMessage(self):
624         user = wFD(self._loggedInUser(u'useruser'))
625         yield user
626         user = user.getResult()
627
628         other = wFD(self._loggedInUser(u'otheruser'))
629         yield other
630         other = other.getResult()
631
632         user.transport.clear()
633         other.transport.clear()
634
635         user.write('PRIVMSG otheruser :Hello, monkey.\r\n')
636
637         response = self._response(user)
638         event = self._response(other)
639
640         self.failIf(response)
641         self.assertEqual(len(event), 1)
642         self.assertEqual(event[0][0], 'useruser!useruser@realmname')
643         self.assertEqual(event[0][1], 'PRIVMSG')
644         self.assertEqual(event[0][2], ['otheruser', 'Hello, monkey.'])
645
646         user.write('PRIVMSG nousernamedthis :Hello, monkey.\r\n')
647
648         response = self._response(user)
649
650         self.assertEqual(len(response), 1)
651         self.assertEqual(response[0][0], 'realmname')
652         self.assertEqual(response[0][1], '401')
653         self.assertEqual(response[0][2], ['useruser', 'nousernamedthis', 'No such nick/channel.'])
654     testPrivateMessage = dG(testPrivateMessage)
655
656
657     def testOper(self):
658         user = wFD(self._loggedInUser(u'useruser'))
659         yield user
660         user = user.getResult()
661
662         user.transport.clear()
663         user.write('OPER user pass\r\n')
664         response = self._response(user)
665
666         self.assertEqual(len(response), 1)
667         self.assertEqual(response[0][1], '491')
668     testOper = dG(testOper)
669
670
671     def testGetUserMode(self):
672         user = wFD(self._loggedInUser(u'useruser'))
673         yield user
674         user = user.getResult()
675
676         user.transport.clear()
677         user.write('MODE useruser\r\n')
678
679         response = self._response(user)
680         self.assertEqual(len(response), 1)
681         self.assertEqual(response[0][0], 'realmname')
682         self.assertEqual(response[0][1], '221')
683         self.assertEqual(response[0][2], ['useruser', '+'])
684     testGetUserMode = dG(testGetUserMode)
685
686
687     def testSetUserMode(self):
688         user = wFD(self._loggedInUser(u'useruser'))
689         yield user
690         user = user.getResult()
691
692         user.transport.clear()
693         user.write('MODE useruser +abcd\r\n')
694
695         response = self._response(user)
696         self.assertEqual(len(response), 1)
697         self.assertEqual(response[0][1], '472')
698     testSetUserMode = dG(testSetUserMode)
699
700
701     def testGetGroupMode(self):
702         user = wFD(self._loggedInUser(u'useruser'))
703         yield user
704         user = user.getResult()
705
706         add = wFD(self.realm.createGroup(u"somechannel"))
707         yield add
708         somechannel = add.getResult()
709
710         user.write('JOIN #somechannel\r\n')
711
712         user.transport.clear()
713         user.write('MODE #somechannel\r\n')
714
715         response = self._response(user)
716         self.assertEqual(len(response), 1)
717         self.assertEqual(response[0][1], '324')
718     testGetGroupMode = dG(testGetGroupMode)
719
720
721     def testSetGroupMode(self):
722         user = wFD(self._loggedInUser(u'useruser'))
723         yield user
724         user = user.getResult()
725
726         group = wFD(self.realm.createGroup(u"groupname"))
727         yield group
728         group = group.getResult()
729
730         user.write('JOIN #groupname\r\n')
731
732         user.transport.clear()
733         user.write('MODE #groupname +abcd\r\n')
734
735         response = self._response(user)
736         self.assertEqual(len(response), 1)
737         self.assertEqual(response[0][1], '472')
738     testSetGroupMode = dG(testSetGroupMode)
739
740
741     def testWho(self):
742         group = service.Group('groupname')
743         add = wFD(self.realm.addGroup(group))
744         yield add
745         add.getResult()
746
747         users = []
748         for nick in u'userone', u'usertwo', u'userthree':
749             u = wFD(self._loggedInUser(nick))
750             yield u
751             u = u.getResult()
752             users.append(u)
753             users[-1].write('JOIN #groupname\r\n')
754         for user in users:
755             user.transport.clear()
756
757         users[0].write('WHO #groupname\r\n')
758
759         r = self._response(users[0])
760         self.failIf(self._response(users[1]))
761         self.failIf(self._response(users[2]))
762
763         wantusers = ['userone', 'usertwo', 'userthree']
764         for (prefix, code, stuff) in r[:-1]:
765             self.assertEqual(prefix, 'realmname')
766             self.assertEqual(code, '352')
767
768             (myname, group, theirname, theirhost, theirserver, theirnick, flag, extra) = stuff
769             self.assertEqual(myname, 'userone')
770             self.assertEqual(group, '#groupname')
771             self.failUnless(theirname in wantusers)
772             self.assertEqual(theirhost, 'realmname')
773             self.assertEqual(theirserver, 'realmname')
774             wantusers.remove(theirnick)
775             self.assertEqual(flag, 'H')
776             self.assertEqual(extra, '0 ' + theirnick)
777         self.failIf(wantusers)
778
779         prefix, code, stuff = r[-1]
780         self.assertEqual(prefix, 'realmname')
781         self.assertEqual(code, '315')
782         myname, channel, extra = stuff
783         self.assertEqual(myname, 'userone')
784         self.assertEqual(channel, '#groupname')
785         self.assertEqual(extra, 'End of /WHO list.')
786     testWho = dG(testWho)
787
788
789     def testList(self):
790         user = wFD(self._loggedInUser(u"someuser"))
791         yield user
792         user = user.getResult()
793         user.transport.clear()
794
795         somegroup = wFD(self.realm.createGroup(u"somegroup"))
796         yield somegroup
797         somegroup = somegroup.getResult()
798         somegroup.size = lambda: succeed(17)
799         somegroup.meta['topic'] = 'this is the topic woo'
800
801         # Test one group
802         user.write('LIST #somegroup\r\n')
803
804         r = self._response(user)
805         self.assertEqual(len(r), 2)
806         resp, end = r
807
808         self.assertEqual(resp[0], 'realmname')
809         self.assertEqual(resp[1], '322')
810         self.assertEqual(resp[2][0], 'someuser')
811         self.assertEqual(resp[2][1], 'somegroup')
812         self.assertEqual(resp[2][2], '17')
813         self.assertEqual(resp[2][3], 'this is the topic woo')
814
815         self.assertEqual(end[0], 'realmname')
816         self.assertEqual(end[1], '323')
817         self.assertEqual(end[2][0], 'someuser')
818         self.assertEqual(end[2][1], 'End of /LIST')
819
820         user.transport.clear()
821         # Test all groups
822
823         user.write('LIST\r\n')
824         r = self._response(user)
825         self.assertEqual(len(r), 2)
826
827         fg1, end = r
828
829         self.assertEqual(fg1[1], '322')
830         self.assertEqual(fg1[2][1], 'somegroup')
831         self.assertEqual(fg1[2][2], '17')
832         self.assertEqual(fg1[2][3], 'this is the topic woo')
833
834         self.assertEqual(end[1], '323')
835     testList = dG(testList)
836
837
838     def testWhois(self):
839         user = wFD(self._loggedInUser(u'someguy'))
840         yield user
841         user = user.getResult()
842
843         otherguy = service.User("otherguy")
844         otherguy.itergroups = lambda: iter([
845             service.Group('groupA'),
846             service.Group('groupB')])
847         otherguy.signOn = 10
848         otherguy.lastMessage = time.time() - 15
849
850         add = wFD(self.realm.addUser(otherguy))
851         yield add
852         add.getResult()
853
854         user.transport.clear()
855         user.write('WHOIS otherguy\r\n')
856         r = self._response(user)
857
858         self.assertEqual(len(r), 5)
859         wuser, wserver, idle, channels, end = r
860
861         self.assertEqual(wuser[0], 'realmname')
862         self.assertEqual(wuser[1], '311')
863         self.assertEqual(wuser[2][0], 'someguy')
864         self.assertEqual(wuser[2][1], 'otherguy')
865         self.assertEqual(wuser[2][2], 'otherguy')
866         self.assertEqual(wuser[2][3], 'realmname')
867         self.assertEqual(wuser[2][4], '*')
868         self.assertEqual(wuser[2][5], 'otherguy')
869
870         self.assertEqual(wserver[0], 'realmname')
871         self.assertEqual(wserver[1], '312')
872         self.assertEqual(wserver[2][0], 'someguy')
873         self.assertEqual(wserver[2][1], 'otherguy')
874         self.assertEqual(wserver[2][2], 'realmname')
875         self.assertEqual(wserver[2][3], 'Hi mom!')
876
877         self.assertEqual(idle[0], 'realmname')
878         self.assertEqual(idle[1], '317')
879         self.assertEqual(idle[2][0], 'someguy')
880         self.assertEqual(idle[2][1], 'otherguy')
881         self.assertEqual(idle[2][2], '15')
882         self.assertEqual(idle[2][3], '10')
883         self.assertEqual(idle[2][4], "seconds idle, signon time")
884
885         self.assertEqual(channels[0], 'realmname')
886         self.assertEqual(channels[1], '319')
887         self.assertEqual(channels[2][0], 'someguy')
888         self.assertEqual(channels[2][1], 'otherguy')
889         self.assertEqual(channels[2][2], '#groupA #groupB')
890
891         self.assertEqual(end[0], 'realmname')
892         self.assertEqual(end[1], '318')
893         self.assertEqual(end[2][0], 'someguy')
894         self.assertEqual(end[2][1], 'otherguy')
895         self.assertEqual(end[2][2], 'End of WHOIS list.')
896     testWhois = dG(testWhois)
897
898
899 class TestMind(service.PBMind):
900     def __init__(self, *a, **kw):
901         self.joins = []
902         self.parts = []
903         self.messages = []
904         self.meta = []
905
906     def remote_userJoined(self, user, group):
907         self.joins.append((user, group))
908
909
910     def remote_userLeft(self, user, group, reason):
911         self.parts.append((user, group, reason))
912
913
914     def remote_receive(self, sender, recipient, message):
915         self.messages.append((sender, recipient, message))
916
917
918     def remote_groupMetaUpdate(self, group, meta):
919         self.meta.append((group, meta))
920 pb.setUnjellyableForClass(TestMind, service.PBMindReference)
921
922
923 class PBProtocolTestCase(unittest.TestCase):
924     def setUp(self):
925         self.realm = service.InMemoryWordsRealm("realmname")
926         self.checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
927         self.portal = portal.Portal(
928             self.realm, [self.checker])
929         self.serverFactory = pb.PBServerFactory(self.portal)
930         self.serverFactory.protocol = self._protocolFactory
931         self.serverFactory.unsafeTracebacks = True
932         self.clientFactory = pb.PBClientFactory()
933         self.clientFactory.unsafeTracebacks = True
934         self.serverPort = reactor.listenTCP(0, self.serverFactory)
935         self.clientConn = reactor.connectTCP(
936             '127.0.0.1',
937             self.serverPort.getHost().port,
938             self.clientFactory)
939
940
941     def _protocolFactory(self, *args, **kw):
942         self._serverProtocol = pb.Broker(0)
943         return self._serverProtocol
944
945
946     def tearDown(self):
947         d3 = Deferred()
948         self._serverProtocol.notifyOnDisconnect(lambda: d3.callback(None))
949         return DeferredList([
950             maybeDeferred(self.serverPort.stopListening),
951             maybeDeferred(self.clientConn.disconnect), d3])
952
953
954     def _loggedInAvatar(self, name, password, mind):
955         creds = credentials.UsernamePassword(name, password)
956         self.checker.addUser(name.encode('ascii'), password)
957         d = self.realm.createUser(name)
958         d.addCallback(lambda ign: self.clientFactory.login(creds, mind))
959         return d
960
961
962     def testGroups(self):
963         mindone = TestMind()
964         one = wFD(self._loggedInAvatar(u"one", "p1", mindone))
965         yield one
966         one = one.getResult()
967
968         mindtwo = TestMind()
969         two = wFD(self._loggedInAvatar(u"two", "p2", mindtwo))
970         yield two
971         two = two.getResult()
972
973         add = wFD(self.realm.createGroup(u"foobar"))
974         yield add
975         add.getResult()
976
977         groupone = wFD(one.join(u"foobar"))
978         yield groupone
979         groupone = groupone.getResult()
980
981         grouptwo = wFD(two.join(u"foobar"))
982         yield grouptwo
983         grouptwo = grouptwo.getResult()
984
985         msg = wFD(groupone.send({"text": "hello, monkeys"}))
986         yield msg
987         msg = msg.getResult()
988
989         leave = wFD(groupone.leave())
990         yield leave
991         leave = leave.getResult()
992     testGroups = dG(testGroups)