1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
5 Tests for L{twisted.words.service}.
10 from twisted.trial import unittest
11 from twisted.test import proto_helpers
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
21 class RealmTestCase(unittest.TestCase):
22 def _entityCreationTest(self, kind):
23 # Kind is "user" or "group"
24 realm = service.InMemoryWordsRealm("realmname")
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())
33 # Creating should succeed
37 self.assertEqual(p.name, name)
39 # Creating the same user again should not
42 self.assertRaises(dupExc, d.getResult)
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()))
49 self.assertEqual(p.name, "new" + kind.lower())
51 # Getting that user again should return the same object
52 d = wFD(get(u"new" + kind.lower()))
55 self.assertIdentical(p, newp)
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()))
61 self.assertRaises(noSuchExc, d.getResult)
62 _entityCreationTest = dG(_entityCreationTest)
65 def testUserCreation(self):
66 return self._entityCreationTest("User")
69 def testGroupCreation(self):
70 return self._entityCreationTest("Group")
73 def testUserRetrieval(self):
74 realm = service.InMemoryWordsRealm("realmname")
76 # Make a user to play around with
77 d = wFD(realm.createUser(u"testuser"))
81 # Make sure getting the user returns the same object
82 d = wFD(realm.getUser(u"testuser"))
84 retrieved = d.getResult()
85 self.assertIdentical(user, retrieved)
87 # Make sure looking up the user also returns the same object
88 d = wFD(realm.lookupUser(u"testuser"))
90 lookedUp = d.getResult()
91 self.assertIdentical(retrieved, lookedUp)
93 # Make sure looking up a user who does not exist fails
94 d = wFD(realm.lookupUser(u"nosuchuser"))
96 self.assertRaises(ewords.NoSuchUser, d.getResult)
97 testUserRetrieval = dG(testUserRetrieval)
100 def testUserAddition(self):
101 realm = service.InMemoryWordsRealm("realmname")
103 # Create and manually add a user to the realm
104 p = service.User("testuser")
105 d = wFD(realm.addUser(p))
108 self.assertIdentical(p, user)
110 # Make sure getting that user returns the same object
111 d = wFD(realm.getUser(u"testuser"))
113 retrieved = d.getResult()
114 self.assertIdentical(user, retrieved)
116 # Make sure looking up that user returns the same object
117 d = wFD(realm.lookupUser(u"testuser"))
119 lookedUp = d.getResult()
120 self.assertIdentical(retrieved, lookedUp)
121 testUserAddition = dG(testUserAddition)
124 def testGroupRetrieval(self):
125 realm = service.InMemoryWordsRealm("realmname")
127 d = wFD(realm.createGroup(u"testgroup"))
129 group = d.getResult()
131 d = wFD(realm.getGroup(u"testgroup"))
133 retrieved = d.getResult()
135 self.assertIdentical(group, retrieved)
137 d = wFD(realm.getGroup(u"nosuchgroup"))
139 self.assertRaises(ewords.NoSuchGroup, d.getResult)
140 testGroupRetrieval = dG(testGroupRetrieval)
143 def testGroupAddition(self):
144 realm = service.InMemoryWordsRealm("realmname")
146 p = service.Group("testgroup")
147 d = wFD(realm.addGroup(p))
151 d = wFD(realm.getGroup(u"testGroup"))
153 group = d.getResult()
155 self.assertIdentical(p, group)
156 testGroupAddition = dG(testGroupAddition)
159 def testGroupUsernameCollision(self):
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.
165 realm = service.InMemoryWordsRealm("realmname")
167 d = wFD(realm.createUser(u"test"))
171 d = wFD(realm.createGroup(u"test"))
173 group = d.getResult()
174 testGroupUsernameCollision = dG(testGroupUsernameCollision)
177 def testEnumeration(self):
178 realm = service.InMemoryWordsRealm("realmname")
179 d = wFD(realm.createGroup(u"groupone"))
183 d = wFD(realm.createGroup(u"grouptwo"))
187 groups = wFD(realm.itergroups())
189 groups = groups.getResult()
191 n = [g.name for g in groups]
193 self.assertEqual(n, ["groupone", "grouptwo"])
194 testEnumeration = dG(testEnumeration)
197 class TestGroup(object):
198 def __init__(self, name, size, topic):
200 self.size = lambda: size
201 self.meta = {'topic': topic}
204 class TestUser(object):
205 def __init__(self, name, groups, signOn, lastMessage):
207 self.itergroups = lambda: iter([TestGroup(g, 3, 'Hello') for g in groups])
209 self.lastMessage = lastMessage
212 class TestPortal(object):
217 def login(self, credentials, mind, *interfaces):
219 self.logins.append((credentials, mind, interfaces, d))
223 class TestCaseUserAgg(object):
224 def __init__(self, user, realm, factory, address=address.IPv4Address('TCP', '127.0.0.1', 54321)):
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)
233 def write(self, stuff):
234 if isinstance(stuff, unicode):
235 stuff = stuff.encode('utf-8')
236 self.protocol.dataReceived(stuff)
239 class IRCProtocolTestCase(unittest.TestCase):
241 u'useruser', u'otheruser', u'someguy', u'firstuser', u'username',
242 u'userone', u'usertwo', u'userthree', u'someuser']
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)
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)
258 def _assertGreeting(self, user):
260 The user has been greeted with the four messages that are (usually)
261 considered to start an IRC session.
263 Asserts that the required responses were received.
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,
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,))
275 def _login(self, user, nick, password=None):
277 password = nick + "_password"
278 user.write('PASS %s\r\n' % (password,))
279 user.write('NICK %s extrainfo\r\n' % (nick,))
282 def _loggedInUser(self, name):
283 d = wFD(self.realm.lookupUser(name))
286 agg = TestCaseUserAgg(user, self.realm, self.factory)
287 self._login(agg, name)
289 _loggedInUser = dG(_loggedInUser)
292 def _response(self, user, messageType=None):
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.
297 response = user.transport.value().splitlines()
298 user.transport.clear()
300 for message in map(irc.parsemsg, response):
301 if messageType is None or message[1] == messageType:
302 result.append(message)
306 def testPASSLogin(self):
307 user = wFD(self._loggedInUser(u'firstuser'))
309 user = user.getResult()
310 self._assertGreeting(user)
311 testPASSLogin = dG(testPASSLogin)
314 def test_nickServLogin(self):
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
320 firstuser = wFD(self.realm.lookupUser(u'firstuser'))
322 firstuser = firstuser.getResult()
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()
333 user.write('PRIVMSG nickserv firstuser_password\r\n')
334 self._assertGreeting(user)
335 test_nickServLogin = dG(test_nickServLogin)
338 def testFailedLogin(self):
339 firstuser = wFD(self.realm.lookupUser(u'firstuser'))
341 firstuser = firstuser.getResult()
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)
351 def testLogout(self):
353 firstuser = wFD(self.realm.lookupUser(u'firstuser'))
355 firstuser = firstuser.getResult()
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)
366 firstuser = wFD(self.realm.lookupUser(u'firstuser'))
368 firstuser = firstuser.getResult()
370 somechannel = wFD(self.realm.createGroup(u"somechannel"))
372 somechannel = somechannel.getResult()
374 somechannel.meta['topic'] = 'some random topic'
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')
382 response = self._response(user)
383 self.assertEqual(len(response), 5)
386 self.assertEqual(response[0][0], 'firstuser!firstuser@realmname')
387 self.assertEqual(response[0][1], 'JOIN')
388 self.assertEqual(response[0][2], ['#somechannel'])
391 self.assertEqual(response[1][1], '353')
392 self.assertEqual(response[2][1], '366')
394 # Topic (or lack thereof, as the case may be)
395 self.assertEqual(response[3][1], '332')
396 self.assertEqual(response[4][1], '333')
399 # Hook up another client! It is a CHAT SYSTEM!!!!!!!
400 other = wFD(self._loggedInUser(u'otheruser'))
402 other = other.getResult()
404 other.transport.clear()
405 user.transport.clear()
406 other.write('JOIN #somechannel\r\n')
408 # At this point, both users should be in the channel
409 response = self._response(other)
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'])
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)
423 def test_joinTopicless(self):
425 When a user joins a group without a topic, no topic information is
428 firstuser = wFD(self.realm.lookupUser(u'firstuser'))
430 firstuser = firstuser.getResult()
432 somechannel = wFD(self.realm.createGroup(u"somechannel"))
434 somechannel = somechannel.getResult()
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')
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)
450 user = wFD(self._loggedInUser(u'useruser'))
452 user = user.getResult()
454 somechannel = wFD(self.realm.createGroup(u"somechannel"))
456 somechannel = somechannel.getResult()
458 user.write('JOIN #somechannel\r\n')
459 user.transport.clear()
461 other = wFD(self._loggedInUser(u'otheruser'))
463 other = other.getResult()
465 other.write('JOIN #somechannel\r\n')
467 user.transport.clear()
468 other.transport.clear()
470 user.write('PART #somechannel\r\n')
472 response = self._response(user)
473 event = self._response(other)
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)
481 # Now again, with a part message
482 user.write('JOIN #somechannel\r\n')
484 user.transport.clear()
485 other.transport.clear()
487 user.write('PART #somechannel :goodbye stupidheads\r\n')
489 response = self._response(user)
490 event = self._response(other)
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)
500 def testGetTopic(self):
501 user = wFD(self._loggedInUser(u'useruser'))
503 user = user.getResult()
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
510 add = wFD(self.realm.addGroup(group))
514 user.transport.clear()
515 user.write("JOIN #somechannel\r\n")
517 response = self._response(user)
519 self.assertEqual(response[3][0], 'realmname')
520 self.assertEqual(response[3][1], '332')
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'])
527 user.transport.clear()
529 user.write('TOPIC #somechannel\r\n')
531 response = self._response(user)
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)
540 def testSetTopic(self):
541 user = wFD(self._loggedInUser(u'useruser'))
543 user = user.getResult()
545 add = wFD(self.realm.createGroup(u"somechannel"))
547 somechannel = add.getResult()
549 user.write("JOIN #somechannel\r\n")
551 other = wFD(self._loggedInUser(u'otheruser'))
553 other = other.getResult()
555 other.write("JOIN #somechannel\r\n")
557 user.transport.clear()
558 other.transport.clear()
560 other.write('TOPIC #somechannel :This is the new topic.\r\n')
562 response = self._response(other)
563 event = self._response(user)
565 self.assertEqual(response, event)
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.'])
571 other.transport.clear()
573 somechannel.meta['topic_date'] = 12345
574 other.write('TOPIC #somechannel\r\n')
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'])
582 other.transport.clear()
583 other.write('TOPIC #asdlkjasd\r\n')
585 response = self._response(other)
586 self.assertEqual(response[0][1], '403')
587 testSetTopic = dG(testSetTopic)
590 def testGroupMessage(self):
591 user = wFD(self._loggedInUser(u'useruser'))
593 user = user.getResult()
595 add = wFD(self.realm.createGroup(u"somechannel"))
597 somechannel = add.getResult()
599 user.write("JOIN #somechannel\r\n")
601 other = wFD(self._loggedInUser(u'otheruser'))
603 other = other.getResult()
605 other.write("JOIN #somechannel\r\n")
607 user.transport.clear()
608 other.transport.clear()
610 user.write('PRIVMSG #somechannel :Hello, world.\r\n')
612 response = self._response(user)
613 event = self._response(other)
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)
623 def testPrivateMessage(self):
624 user = wFD(self._loggedInUser(u'useruser'))
626 user = user.getResult()
628 other = wFD(self._loggedInUser(u'otheruser'))
630 other = other.getResult()
632 user.transport.clear()
633 other.transport.clear()
635 user.write('PRIVMSG otheruser :Hello, monkey.\r\n')
637 response = self._response(user)
638 event = self._response(other)
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.'])
646 user.write('PRIVMSG nousernamedthis :Hello, monkey.\r\n')
648 response = self._response(user)
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)
658 user = wFD(self._loggedInUser(u'useruser'))
660 user = user.getResult()
662 user.transport.clear()
663 user.write('OPER user pass\r\n')
664 response = self._response(user)
666 self.assertEqual(len(response), 1)
667 self.assertEqual(response[0][1], '491')
668 testOper = dG(testOper)
671 def testGetUserMode(self):
672 user = wFD(self._loggedInUser(u'useruser'))
674 user = user.getResult()
676 user.transport.clear()
677 user.write('MODE useruser\r\n')
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)
687 def testSetUserMode(self):
688 user = wFD(self._loggedInUser(u'useruser'))
690 user = user.getResult()
692 user.transport.clear()
693 user.write('MODE useruser +abcd\r\n')
695 response = self._response(user)
696 self.assertEqual(len(response), 1)
697 self.assertEqual(response[0][1], '472')
698 testSetUserMode = dG(testSetUserMode)
701 def testGetGroupMode(self):
702 user = wFD(self._loggedInUser(u'useruser'))
704 user = user.getResult()
706 add = wFD(self.realm.createGroup(u"somechannel"))
708 somechannel = add.getResult()
710 user.write('JOIN #somechannel\r\n')
712 user.transport.clear()
713 user.write('MODE #somechannel\r\n')
715 response = self._response(user)
716 self.assertEqual(len(response), 1)
717 self.assertEqual(response[0][1], '324')
718 testGetGroupMode = dG(testGetGroupMode)
721 def testSetGroupMode(self):
722 user = wFD(self._loggedInUser(u'useruser'))
724 user = user.getResult()
726 group = wFD(self.realm.createGroup(u"groupname"))
728 group = group.getResult()
730 user.write('JOIN #groupname\r\n')
732 user.transport.clear()
733 user.write('MODE #groupname +abcd\r\n')
735 response = self._response(user)
736 self.assertEqual(len(response), 1)
737 self.assertEqual(response[0][1], '472')
738 testSetGroupMode = dG(testSetGroupMode)
742 group = service.Group('groupname')
743 add = wFD(self.realm.addGroup(group))
748 for nick in u'userone', u'usertwo', u'userthree':
749 u = wFD(self._loggedInUser(nick))
753 users[-1].write('JOIN #groupname\r\n')
755 user.transport.clear()
757 users[0].write('WHO #groupname\r\n')
759 r = self._response(users[0])
760 self.failIf(self._response(users[1]))
761 self.failIf(self._response(users[2]))
763 wantusers = ['userone', 'usertwo', 'userthree']
764 for (prefix, code, stuff) in r[:-1]:
765 self.assertEqual(prefix, 'realmname')
766 self.assertEqual(code, '352')
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)
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)
790 user = wFD(self._loggedInUser(u"someuser"))
792 user = user.getResult()
793 user.transport.clear()
795 somegroup = wFD(self.realm.createGroup(u"somegroup"))
797 somegroup = somegroup.getResult()
798 somegroup.size = lambda: succeed(17)
799 somegroup.meta['topic'] = 'this is the topic woo'
802 user.write('LIST #somegroup\r\n')
804 r = self._response(user)
805 self.assertEqual(len(r), 2)
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')
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')
820 user.transport.clear()
823 user.write('LIST\r\n')
824 r = self._response(user)
825 self.assertEqual(len(r), 2)
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')
834 self.assertEqual(end[1], '323')
835 testList = dG(testList)
839 user = wFD(self._loggedInUser(u'someguy'))
841 user = user.getResult()
843 otherguy = service.User("otherguy")
844 otherguy.itergroups = lambda: iter([
845 service.Group('groupA'),
846 service.Group('groupB')])
848 otherguy.lastMessage = time.time() - 15
850 add = wFD(self.realm.addUser(otherguy))
854 user.transport.clear()
855 user.write('WHOIS otherguy\r\n')
856 r = self._response(user)
858 self.assertEqual(len(r), 5)
859 wuser, wserver, idle, channels, end = r
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')
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!')
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")
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')
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)
899 class TestMind(service.PBMind):
900 def __init__(self, *a, **kw):
906 def remote_userJoined(self, user, group):
907 self.joins.append((user, group))
910 def remote_userLeft(self, user, group, reason):
911 self.parts.append((user, group, reason))
914 def remote_receive(self, sender, recipient, message):
915 self.messages.append((sender, recipient, message))
918 def remote_groupMetaUpdate(self, group, meta):
919 self.meta.append((group, meta))
920 pb.setUnjellyableForClass(TestMind, service.PBMindReference)
923 class PBProtocolTestCase(unittest.TestCase):
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(
937 self.serverPort.getHost().port,
941 def _protocolFactory(self, *args, **kw):
942 self._serverProtocol = pb.Broker(0)
943 return self._serverProtocol
948 self._serverProtocol.notifyOnDisconnect(lambda: d3.callback(None))
949 return DeferredList([
950 maybeDeferred(self.serverPort.stopListening),
951 maybeDeferred(self.clientConn.disconnect), d3])
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))
962 def testGroups(self):
964 one = wFD(self._loggedInAvatar(u"one", "p1", mindone))
966 one = one.getResult()
969 two = wFD(self._loggedInAvatar(u"two", "p2", mindtwo))
971 two = two.getResult()
973 add = wFD(self.realm.createGroup(u"foobar"))
977 groupone = wFD(one.join(u"foobar"))
979 groupone = groupone.getResult()
981 grouptwo = wFD(two.join(u"foobar"))
983 grouptwo = grouptwo.getResult()
985 msg = wFD(groupone.send({"text": "hello, monkeys"}))
987 msg = msg.getResult()
989 leave = wFD(groupone.leave())
991 leave = leave.getResult()
992 testGroups = dG(testGroups)