test_service.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for L{twisted.words.service}.
  5. """
  6. import time
  7. from twisted.cred import portal, credentials, checkers
  8. from twisted.internet import address, defer, reactor
  9. from twisted.internet.defer import Deferred, DeferredList, maybeDeferred, succeed
  10. from twisted.python.compat import unicode
  11. from twisted.spread import pb
  12. from twisted.test import proto_helpers
  13. from twisted.trial import unittest
  14. from twisted.words import ewords, service
  15. from twisted.words.protocols import irc
  16. class RealmTests(unittest.TestCase):
  17. def _entityCreationTest(self, kind):
  18. # Kind is "user" or "group"
  19. realm = service.InMemoryWordsRealm("realmname")
  20. name = u'test' + kind.lower()
  21. create = getattr(realm, 'create' + kind.title())
  22. get = getattr(realm, 'get' + kind.title())
  23. flag = 'create' + kind.title() + 'OnRequest'
  24. dupExc = getattr(ewords, 'Duplicate' + kind.title())
  25. noSuchExc = getattr(ewords, 'NoSuch' + kind.title())
  26. # Creating should succeed
  27. p = self.successResultOf(create(name))
  28. self.assertEqual(name, p.name)
  29. # Creating the same user again should not
  30. self.failureResultOf(create(name)).trap(dupExc)
  31. # Getting a non-existent user should succeed if createUserOnRequest is True
  32. setattr(realm, flag, True)
  33. p = self.successResultOf(get(u"new" + kind.lower()))
  34. self.assertEqual("new" + kind.lower(), p.name)
  35. # Getting that user again should return the same object
  36. newp = self.successResultOf(get(u"new" + kind.lower()))
  37. self.assertIdentical(p, newp)
  38. # Getting a non-existent user should fail if createUserOnRequest is False
  39. setattr(realm, flag, False)
  40. self.failureResultOf(get(u"another" + kind.lower())).trap(noSuchExc)
  41. def testUserCreation(self):
  42. return self._entityCreationTest("User")
  43. def testGroupCreation(self):
  44. return self._entityCreationTest("Group")
  45. def testUserRetrieval(self):
  46. realm = service.InMemoryWordsRealm("realmname")
  47. # Make a user to play around with
  48. user = self.successResultOf(realm.createUser(u"testuser"))
  49. # Make sure getting the user returns the same object
  50. retrieved = self.successResultOf(realm.getUser(u"testuser"))
  51. self.assertIdentical(user, retrieved)
  52. # Make sure looking up the user also returns the same object
  53. lookedUp = self.successResultOf(realm.lookupUser(u"testuser"))
  54. self.assertIdentical(retrieved, lookedUp)
  55. # Make sure looking up a user who does not exist fails
  56. (self.failureResultOf(realm.lookupUser(u"nosuchuser"))
  57. .trap(ewords.NoSuchUser))
  58. def testUserAddition(self):
  59. realm = service.InMemoryWordsRealm("realmname")
  60. # Create and manually add a user to the realm
  61. p = service.User("testuser")
  62. user = self.successResultOf(realm.addUser(p))
  63. self.assertIdentical(p, user)
  64. # Make sure getting that user returns the same object
  65. retrieved = self.successResultOf(realm.getUser(u"testuser"))
  66. self.assertIdentical(user, retrieved)
  67. # Make sure looking up that user returns the same object
  68. lookedUp = self.successResultOf(realm.lookupUser(u"testuser"))
  69. self.assertIdentical(retrieved, lookedUp)
  70. def testGroupRetrieval(self):
  71. realm = service.InMemoryWordsRealm("realmname")
  72. group = self.successResultOf(realm.createGroup(u"testgroup"))
  73. retrieved = self.successResultOf(realm.getGroup(u"testgroup"))
  74. self.assertIdentical(group, retrieved)
  75. (self.failureResultOf(realm.getGroup(u"nosuchgroup"))
  76. .trap(ewords.NoSuchGroup))
  77. def testGroupAddition(self):
  78. realm = service.InMemoryWordsRealm("realmname")
  79. p = service.Group("testgroup")
  80. self.successResultOf(realm.addGroup(p))
  81. group = self.successResultOf(realm.getGroup(u"testGroup"))
  82. self.assertIdentical(p, group)
  83. def testGroupUsernameCollision(self):
  84. """
  85. Try creating a group with the same name as an existing user and
  86. assert that it succeeds, since users and groups should not be in the
  87. same namespace and collisions should be impossible.
  88. """
  89. realm = service.InMemoryWordsRealm("realmname")
  90. self.successResultOf(realm.createUser(u"test"))
  91. self.successResultOf(realm.createGroup(u"test"))
  92. def testEnumeration(self):
  93. realm = service.InMemoryWordsRealm("realmname")
  94. self.successResultOf(realm.createGroup(u"groupone"))
  95. self.successResultOf(realm.createGroup(u"grouptwo"))
  96. groups = self.successResultOf(realm.itergroups())
  97. n = [g.name for g in groups]
  98. n.sort()
  99. self.assertEqual(n, ["groupone", "grouptwo"])
  100. class TestCaseUserAgg(object):
  101. def __init__(self, user, realm, factory, address=address.IPv4Address('TCP', '127.0.0.1', 54321)):
  102. self.user = user
  103. self.transport = proto_helpers.StringTransportWithDisconnection()
  104. self.protocol = factory.buildProtocol(address)
  105. self.transport.protocol = self.protocol
  106. self.user.mind = self.protocol
  107. self.protocol.makeConnection(self.transport)
  108. def write(self, stuff):
  109. self.protocol.dataReceived(stuff)
  110. class IRCProtocolTests(unittest.TestCase):
  111. STATIC_USERS = [
  112. u'useruser', u'otheruser', u'someguy', u'firstuser', u'username',
  113. u'userone', u'usertwo', u'userthree', 'userfour', b'userfive', u'someuser']
  114. def setUp(self):
  115. self.realm = service.InMemoryWordsRealm("realmname")
  116. self.checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
  117. self.portal = portal.Portal(self.realm, [self.checker])
  118. self.factory = service.IRCFactory(self.realm, self.portal)
  119. c = []
  120. for nick in self.STATIC_USERS:
  121. if isinstance(nick, bytes):
  122. nick = nick.decode("utf-8")
  123. c.append(self.realm.createUser(nick))
  124. self.checker.addUser(nick, nick + u"_password")
  125. return DeferredList(c)
  126. def _assertGreeting(self, user):
  127. """
  128. The user has been greeted with the four messages that are (usually)
  129. considered to start an IRC session.
  130. Asserts that the required responses were received.
  131. """
  132. # Make sure we get 1-4 at least
  133. response = self._response(user)
  134. expected = [irc.RPL_WELCOME, irc.RPL_YOURHOST, irc.RPL_CREATED,
  135. irc.RPL_MYINFO]
  136. for (prefix, command, args) in response:
  137. if command in expected:
  138. expected.remove(command)
  139. self.assertFalse(expected, "Missing responses for %r" % (expected,))
  140. def _login(self, user, nick, password=None):
  141. if password is None:
  142. password = nick + "_password"
  143. user.write(u'PASS %s\r\n' % (password,))
  144. user.write(u'NICK %s extrainfo\r\n' % (nick,))
  145. def _loggedInUser(self, name):
  146. user = self.successResultOf(self.realm.lookupUser(name))
  147. agg = TestCaseUserAgg(user, self.realm, self.factory)
  148. self._login(agg, name)
  149. return agg
  150. def _response(self, user, messageType=None):
  151. """
  152. Extracts the user's response, and returns a list of parsed lines.
  153. If messageType is defined, only messages of that type will be returned.
  154. """
  155. response = user.transport.value()
  156. if bytes != str and isinstance(response, bytes):
  157. response = response.decode("utf-8")
  158. response = response.splitlines()
  159. user.transport.clear()
  160. result = []
  161. for message in map(irc.parsemsg, response):
  162. if messageType is None or message[1] == messageType:
  163. result.append(message)
  164. return result
  165. def testPASSLogin(self):
  166. user = self._loggedInUser(u'firstuser')
  167. self._assertGreeting(user)
  168. def test_nickServLogin(self):
  169. """
  170. Sending NICK without PASS will prompt the user for their password.
  171. When the user sends their password to NickServ, it will respond with a
  172. Greeting.
  173. """
  174. firstuser = self.successResultOf(self.realm.lookupUser(u'firstuser'))
  175. user = TestCaseUserAgg(firstuser, self.realm, self.factory)
  176. user.write('NICK firstuser extrainfo\r\n')
  177. response = self._response(user, 'PRIVMSG')
  178. self.assertEqual(len(response), 1)
  179. self.assertEqual(response[0][0], service.NICKSERV)
  180. self.assertEqual(response[0][1], 'PRIVMSG')
  181. self.assertEqual(response[0][2], ['firstuser', 'Password?'])
  182. user.transport.clear()
  183. user.write('PRIVMSG nickserv firstuser_password\r\n')
  184. self._assertGreeting(user)
  185. def testFailedLogin(self):
  186. firstuser = self.successResultOf(self.realm.lookupUser(u'firstuser'))
  187. user = TestCaseUserAgg(firstuser, self.realm, self.factory)
  188. self._login(user, u"firstuser", u"wrongpass")
  189. response = self._response(user, "PRIVMSG")
  190. self.assertEqual(len(response), 1)
  191. self.assertEqual(response[0][2], ['firstuser', 'Login failed. Goodbye.'])
  192. def testLogout(self):
  193. logout = []
  194. firstuser = self.successResultOf(self.realm.lookupUser(u'firstuser'))
  195. user = TestCaseUserAgg(firstuser, self.realm, self.factory)
  196. self._login(user, "firstuser")
  197. user.protocol.logout = lambda: logout.append(True)
  198. user.write('QUIT\r\n')
  199. self.assertEqual(logout, [True])
  200. def testJoin(self):
  201. firstuser = self.successResultOf(self.realm.lookupUser(u'firstuser'))
  202. somechannel = self.successResultOf(
  203. self.realm.createGroup(u"somechannel"))
  204. somechannel.meta['topic'] = 'some random topic'
  205. # Bring in one user, make sure he gets into the channel sanely
  206. user = TestCaseUserAgg(firstuser, self.realm, self.factory)
  207. self._login(user, "firstuser")
  208. user.transport.clear()
  209. user.write('JOIN #somechannel\r\n')
  210. response = self._response(user)
  211. self.assertEqual(len(response), 5)
  212. # Join message
  213. self.assertEqual(response[0][0], 'firstuser!firstuser@realmname')
  214. self.assertEqual(response[0][1], 'JOIN')
  215. self.assertEqual(response[0][2], ['#somechannel'])
  216. # User list
  217. self.assertEqual(response[1][1], '353')
  218. self.assertEqual(response[2][1], '366')
  219. # Topic (or lack thereof, as the case may be)
  220. self.assertEqual(response[3][1], '332')
  221. self.assertEqual(response[4][1], '333')
  222. # Hook up another client! It is a CHAT SYSTEM!!!!!!!
  223. other = self._loggedInUser(u'otheruser')
  224. other.transport.clear()
  225. user.transport.clear()
  226. other.write('JOIN #somechannel\r\n')
  227. # At this point, both users should be in the channel
  228. response = self._response(other)
  229. event = self._response(user)
  230. self.assertEqual(len(event), 1)
  231. self.assertEqual(event[0][0], 'otheruser!otheruser@realmname')
  232. self.assertEqual(event[0][1], 'JOIN')
  233. self.assertEqual(event[0][2], ['#somechannel'])
  234. self.assertEqual(response[1][0], 'realmname')
  235. self.assertEqual(response[1][1], '353')
  236. self.assertIn(response[1][2], [
  237. ['otheruser', '=', '#somechannel', 'firstuser otheruser'],
  238. ['otheruser', '=', '#somechannel', 'otheruser firstuser'],
  239. ])
  240. def test_joinTopicless(self):
  241. """
  242. When a user joins a group without a topic, no topic information is
  243. sent to that user.
  244. """
  245. firstuser = self.successResultOf(self.realm.lookupUser(u'firstuser'))
  246. self.successResultOf(self.realm.createGroup(u"somechannel"))
  247. # Bring in one user, make sure he gets into the channel sanely
  248. user = TestCaseUserAgg(firstuser, self.realm, self.factory)
  249. self._login(user, "firstuser")
  250. user.transport.clear()
  251. user.write('JOIN #somechannel\r\n')
  252. response = self._response(user)
  253. responseCodes = [r[1] for r in response]
  254. self.assertNotIn('332', responseCodes)
  255. self.assertNotIn('333', responseCodes)
  256. def testLeave(self):
  257. user = self._loggedInUser(u'useruser')
  258. self.successResultOf(self.realm.createGroup(u"somechannel"))
  259. user.write('JOIN #somechannel\r\n')
  260. user.transport.clear()
  261. other = self._loggedInUser(u'otheruser')
  262. other.write('JOIN #somechannel\r\n')
  263. user.transport.clear()
  264. other.transport.clear()
  265. user.write('PART #somechannel\r\n')
  266. response = self._response(user)
  267. event = self._response(other)
  268. self.assertEqual(len(response), 1)
  269. self.assertEqual(response[0][0], 'useruser!useruser@realmname')
  270. self.assertEqual(response[0][1], 'PART')
  271. self.assertEqual(response[0][2], ['#somechannel', 'leaving'])
  272. self.assertEqual(response, event)
  273. # Now again, with a part message
  274. user.write('JOIN #somechannel\r\n')
  275. user.transport.clear()
  276. other.transport.clear()
  277. user.write('PART #somechannel :goodbye stupidheads\r\n')
  278. response = self._response(user)
  279. event = self._response(other)
  280. self.assertEqual(len(response), 1)
  281. self.assertEqual(response[0][0], 'useruser!useruser@realmname')
  282. self.assertEqual(response[0][1], 'PART')
  283. self.assertEqual(response[0][2], ['#somechannel', 'goodbye stupidheads'])
  284. self.assertEqual(response, event)
  285. user.write(b'JOIN #somechannel\r\n')
  286. user.transport.clear()
  287. other.transport.clear()
  288. user.write(b'PART #somechannel :goodbye stupidheads1\r\n')
  289. response = self._response(user)
  290. event = self._response(other)
  291. self.assertEqual(len(response), 1)
  292. self.assertEqual(response[0][0], 'useruser!useruser@realmname')
  293. self.assertEqual(response[0][1], 'PART')
  294. self.assertEqual(response[0][2], ['#somechannel', 'goodbye stupidheads1'])
  295. self.assertEqual(response, event)
  296. def testGetTopic(self):
  297. user = self._loggedInUser(u'useruser')
  298. group = service.Group("somechannel")
  299. group.meta["topic"] = "This is a test topic."
  300. group.meta["topic_author"] = "some_fellow"
  301. group.meta["topic_date"] = 77777777
  302. self.successResultOf(self.realm.addGroup(group))
  303. user.transport.clear()
  304. user.write("JOIN #somechannel\r\n")
  305. response = self._response(user)
  306. self.assertEqual(response[3][0], 'realmname')
  307. self.assertEqual(response[3][1], '332')
  308. # XXX Sigh. irc.parsemsg() is not as correct as one might hope.
  309. self.assertEqual(response[3][2], ['useruser', '#somechannel', 'This is a test topic.'])
  310. self.assertEqual(response[4][1], '333')
  311. self.assertEqual(response[4][2], ['useruser', '#somechannel', 'some_fellow', '77777777'])
  312. user.transport.clear()
  313. user.write('TOPIC #somechannel\r\n')
  314. response = self._response(user)
  315. self.assertEqual(response[0][1], '332')
  316. self.assertEqual(response[0][2], ['useruser', '#somechannel', 'This is a test topic.'])
  317. self.assertEqual(response[1][1], '333')
  318. self.assertEqual(response[1][2], ['useruser', '#somechannel', 'some_fellow', '77777777'])
  319. def testSetTopic(self):
  320. user = self._loggedInUser(u'useruser')
  321. somechannel = self.successResultOf(
  322. self.realm.createGroup(u"somechannel"))
  323. user.write("JOIN #somechannel\r\n")
  324. other = self._loggedInUser(u'otheruser')
  325. other.write("JOIN #somechannel\r\n")
  326. user.transport.clear()
  327. other.transport.clear()
  328. other.write('TOPIC #somechannel :This is the new topic.\r\n')
  329. response = self._response(other)
  330. event = self._response(user)
  331. self.assertEqual(response, event)
  332. self.assertEqual(response[0][0], 'otheruser!otheruser@realmname')
  333. self.assertEqual(response[0][1], 'TOPIC')
  334. self.assertEqual(response[0][2], ['#somechannel', 'This is the new topic.'])
  335. other.transport.clear()
  336. somechannel.meta['topic_date'] = 12345
  337. other.write('TOPIC #somechannel\r\n')
  338. response = self._response(other)
  339. self.assertEqual(response[0][1], '332')
  340. self.assertEqual(response[0][2], ['otheruser', '#somechannel', 'This is the new topic.'])
  341. self.assertEqual(response[1][1], '333')
  342. self.assertEqual(response[1][2], ['otheruser', '#somechannel', 'otheruser', '12345'])
  343. other.transport.clear()
  344. other.write('TOPIC #asdlkjasd\r\n')
  345. response = self._response(other)
  346. self.assertEqual(response[0][1], '403')
  347. def testGroupMessage(self):
  348. user = self._loggedInUser(u'useruser')
  349. self.successResultOf(self.realm.createGroup(u"somechannel"))
  350. user.write("JOIN #somechannel\r\n")
  351. other = self._loggedInUser(u'otheruser')
  352. other.write("JOIN #somechannel\r\n")
  353. user.transport.clear()
  354. other.transport.clear()
  355. user.write('PRIVMSG #somechannel :Hello, world.\r\n')
  356. response = self._response(user)
  357. event = self._response(other)
  358. self.assertFalse(response)
  359. self.assertEqual(len(event), 1)
  360. self.assertEqual(event[0][0], 'useruser!useruser@realmname')
  361. self.assertEqual(event[0][1], 'PRIVMSG', -1)
  362. self.assertEqual(event[0][2], ['#somechannel', 'Hello, world.'])
  363. def testPrivateMessage(self):
  364. user = self._loggedInUser(u'useruser')
  365. other = self._loggedInUser(u'otheruser')
  366. user.transport.clear()
  367. other.transport.clear()
  368. user.write('PRIVMSG otheruser :Hello, monkey.\r\n')
  369. response = self._response(user)
  370. event = self._response(other)
  371. self.assertFalse(response)
  372. self.assertEqual(len(event), 1)
  373. self.assertEqual(event[0][0], 'useruser!useruser@realmname')
  374. self.assertEqual(event[0][1], 'PRIVMSG')
  375. self.assertEqual(event[0][2], ['otheruser', 'Hello, monkey.'])
  376. user.write('PRIVMSG nousernamedthis :Hello, monkey.\r\n')
  377. response = self._response(user)
  378. self.assertEqual(len(response), 1)
  379. self.assertEqual(response[0][0], 'realmname')
  380. self.assertEqual(response[0][1], '401')
  381. self.assertEqual(response[0][2], ['useruser', 'nousernamedthis', 'No such nick/channel.'])
  382. def testOper(self):
  383. user = self._loggedInUser(u'useruser')
  384. user.transport.clear()
  385. user.write('OPER user pass\r\n')
  386. response = self._response(user)
  387. self.assertEqual(len(response), 1)
  388. self.assertEqual(response[0][1], '491')
  389. def testGetUserMode(self):
  390. user = self._loggedInUser(u'useruser')
  391. user.transport.clear()
  392. user.write('MODE useruser\r\n')
  393. response = self._response(user)
  394. self.assertEqual(len(response), 1)
  395. self.assertEqual(response[0][0], 'realmname')
  396. self.assertEqual(response[0][1], '221')
  397. self.assertEqual(response[0][2], ['useruser', '+'])
  398. def testSetUserMode(self):
  399. user = self._loggedInUser(u'useruser')
  400. user.transport.clear()
  401. user.write('MODE useruser +abcd\r\n')
  402. response = self._response(user)
  403. self.assertEqual(len(response), 1)
  404. self.assertEqual(response[0][1], '472')
  405. def testGetGroupMode(self):
  406. user = self._loggedInUser(u'useruser')
  407. self.successResultOf(self.realm.createGroup(u"somechannel"))
  408. user.write('JOIN #somechannel\r\n')
  409. user.transport.clear()
  410. user.write('MODE #somechannel\r\n')
  411. response = self._response(user)
  412. self.assertEqual(len(response), 1)
  413. self.assertEqual(response[0][1], '324')
  414. def testSetGroupMode(self):
  415. user = self._loggedInUser(u'useruser')
  416. self.successResultOf(self.realm.createGroup(u"groupname"))
  417. user.write('JOIN #groupname\r\n')
  418. user.transport.clear()
  419. user.write('MODE #groupname +abcd\r\n')
  420. response = self._response(user)
  421. self.assertEqual(len(response), 1)
  422. self.assertEqual(response[0][1], '472')
  423. def testWho(self):
  424. group = service.Group('groupname')
  425. self.successResultOf(self.realm.addGroup(group))
  426. users = []
  427. for nick in u'userone', u'usertwo', u'userthree':
  428. u = self._loggedInUser(nick)
  429. users.append(u)
  430. users[-1].write('JOIN #groupname\r\n')
  431. for user in users:
  432. user.transport.clear()
  433. users[0].write('WHO #groupname\r\n')
  434. r = self._response(users[0])
  435. self.assertFalse(self._response(users[1]))
  436. self.assertFalse(self._response(users[2]))
  437. wantusers = ['userone', 'usertwo', 'userthree']
  438. for (prefix, code, stuff) in r[:-1]:
  439. self.assertEqual(prefix, 'realmname')
  440. self.assertEqual(code, '352')
  441. (myname, group, theirname, theirhost, theirserver, theirnick, flag, extra) = stuff
  442. self.assertEqual(myname, 'userone')
  443. self.assertEqual(group, '#groupname')
  444. self.assertTrue(theirname in wantusers)
  445. self.assertEqual(theirhost, 'realmname')
  446. self.assertEqual(theirserver, 'realmname')
  447. wantusers.remove(theirnick)
  448. self.assertEqual(flag, 'H')
  449. self.assertEqual(extra, '0 ' + theirnick)
  450. self.assertFalse(wantusers)
  451. prefix, code, stuff = r[-1]
  452. self.assertEqual(prefix, 'realmname')
  453. self.assertEqual(code, '315')
  454. myname, channel, extra = stuff
  455. self.assertEqual(myname, 'userone')
  456. self.assertEqual(channel, '#groupname')
  457. self.assertEqual(extra, 'End of /WHO list.')
  458. def testList(self):
  459. user = self._loggedInUser(u"someuser")
  460. user.transport.clear()
  461. somegroup = self.successResultOf(self.realm.createGroup(u"somegroup"))
  462. somegroup.size = lambda: succeed(17)
  463. somegroup.meta['topic'] = 'this is the topic woo'
  464. # Test one group
  465. user.write('LIST #somegroup\r\n')
  466. r = self._response(user)
  467. self.assertEqual(len(r), 2)
  468. resp, end = r
  469. self.assertEqual(resp[0], 'realmname')
  470. self.assertEqual(resp[1], '322')
  471. self.assertEqual(resp[2][0], 'someuser')
  472. self.assertEqual(resp[2][1], 'somegroup')
  473. self.assertEqual(resp[2][2], '17')
  474. self.assertEqual(resp[2][3], 'this is the topic woo')
  475. self.assertEqual(end[0], 'realmname')
  476. self.assertEqual(end[1], '323')
  477. self.assertEqual(end[2][0], 'someuser')
  478. self.assertEqual(end[2][1], 'End of /LIST')
  479. user.transport.clear()
  480. # Test all groups
  481. user.write('LIST\r\n')
  482. r = self._response(user)
  483. self.assertEqual(len(r), 2)
  484. fg1, end = r
  485. self.assertEqual(fg1[1], '322')
  486. self.assertEqual(fg1[2][1], 'somegroup')
  487. self.assertEqual(fg1[2][2], '17')
  488. self.assertEqual(fg1[2][3], 'this is the topic woo')
  489. self.assertEqual(end[1], '323')
  490. def testWhois(self):
  491. user = self._loggedInUser(u'someguy')
  492. otherguy = service.User("otherguy")
  493. otherguy.itergroups = lambda: iter([
  494. service.Group('groupA'),
  495. service.Group('groupB')])
  496. otherguy.signOn = 10
  497. otherguy.lastMessage = time.time() - 15
  498. self.successResultOf(self.realm.addUser(otherguy))
  499. user.transport.clear()
  500. user.write('WHOIS otherguy\r\n')
  501. r = self._response(user)
  502. self.assertEqual(len(r), 5)
  503. wuser, wserver, idle, channels, end = r
  504. self.assertEqual(wuser[0], 'realmname')
  505. self.assertEqual(wuser[1], '311')
  506. self.assertEqual(wuser[2][0], 'someguy')
  507. self.assertEqual(wuser[2][1], 'otherguy')
  508. self.assertEqual(wuser[2][2], 'otherguy')
  509. self.assertEqual(wuser[2][3], 'realmname')
  510. self.assertEqual(wuser[2][4], '*')
  511. self.assertEqual(wuser[2][5], 'otherguy')
  512. self.assertEqual(wserver[0], 'realmname')
  513. self.assertEqual(wserver[1], '312')
  514. self.assertEqual(wserver[2][0], 'someguy')
  515. self.assertEqual(wserver[2][1], 'otherguy')
  516. self.assertEqual(wserver[2][2], 'realmname')
  517. self.assertEqual(wserver[2][3], 'Hi mom!')
  518. self.assertEqual(idle[0], 'realmname')
  519. self.assertEqual(idle[1], '317')
  520. self.assertEqual(idle[2][0], 'someguy')
  521. self.assertEqual(idle[2][1], 'otherguy')
  522. self.assertEqual(idle[2][2], '15')
  523. self.assertEqual(idle[2][3], '10')
  524. self.assertEqual(idle[2][4], "seconds idle, signon time")
  525. self.assertEqual(channels[0], 'realmname')
  526. self.assertEqual(channels[1], '319')
  527. self.assertEqual(channels[2][0], 'someguy')
  528. self.assertEqual(channels[2][1], 'otherguy')
  529. self.assertEqual(channels[2][2], '#groupA #groupB')
  530. self.assertEqual(end[0], 'realmname')
  531. self.assertEqual(end[1], '318')
  532. self.assertEqual(end[2][0], 'someguy')
  533. self.assertEqual(end[2][1], 'otherguy')
  534. self.assertEqual(end[2][2], 'End of WHOIS list.')
  535. class TestMind(service.PBMind):
  536. def __init__(self, *a, **kw):
  537. self.joins = []
  538. self.parts = []
  539. self.messages = []
  540. self.meta = []
  541. def remote_userJoined(self, user, group):
  542. self.joins.append((user, group))
  543. def remote_userLeft(self, user, group, reason):
  544. self.parts.append((user, group, reason))
  545. def remote_receive(self, sender, recipient, message):
  546. self.messages.append((sender, recipient, message))
  547. def remote_groupMetaUpdate(self, group, meta):
  548. self.meta.append((group, meta))
  549. pb.setUnjellyableForClass(TestMind, service.PBMindReference)
  550. class PBProtocolTests(unittest.TestCase):
  551. def setUp(self):
  552. self.realm = service.InMemoryWordsRealm("realmname")
  553. self.checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
  554. self.portal = portal.Portal(
  555. self.realm, [self.checker])
  556. self.serverFactory = pb.PBServerFactory(self.portal)
  557. self.serverFactory.protocol = self._protocolFactory
  558. self.serverFactory.unsafeTracebacks = True
  559. self.clientFactory = pb.PBClientFactory()
  560. self.clientFactory.unsafeTracebacks = True
  561. self.serverPort = reactor.listenTCP(0, self.serverFactory)
  562. self.clientConn = reactor.connectTCP(
  563. '127.0.0.1',
  564. self.serverPort.getHost().port,
  565. self.clientFactory)
  566. def _protocolFactory(self, *args, **kw):
  567. self._serverProtocol = pb.Broker(0)
  568. return self._serverProtocol
  569. def tearDown(self):
  570. d3 = Deferred()
  571. self._serverProtocol.notifyOnDisconnect(lambda: d3.callback(None))
  572. return DeferredList([
  573. maybeDeferred(self.serverPort.stopListening),
  574. maybeDeferred(self.clientConn.disconnect), d3])
  575. def _loggedInAvatar(self, name, password, mind):
  576. nameBytes = name
  577. if isinstance(name, unicode):
  578. nameBytes = name.encode("ascii")
  579. creds = credentials.UsernamePassword(nameBytes, password)
  580. self.checker.addUser(nameBytes, password)
  581. d = self.realm.createUser(name)
  582. d.addCallback(lambda ign: self.clientFactory.login(creds, mind))
  583. return d
  584. @defer.inlineCallbacks
  585. def testGroups(self):
  586. mindone = TestMind()
  587. one = yield self._loggedInAvatar(u"one", b"p1", mindone)
  588. mindtwo = TestMind()
  589. two = yield self._loggedInAvatar(u"two", b"p2", mindtwo)
  590. mindThree = TestMind()
  591. three = yield self._loggedInAvatar(b"three", b"p3", mindThree)
  592. yield self.realm.createGroup(u"foobar")
  593. yield self.realm.createGroup(b"barfoo")
  594. groupone = yield one.join(u"foobar")
  595. grouptwo = yield two.join(b"barfoo")
  596. yield two.join(u"foobar")
  597. yield two.join(b"barfoo")
  598. yield three.join(u"foobar")
  599. yield groupone.send({b"text": b"hello, monkeys"})
  600. yield groupone.leave()
  601. yield grouptwo.leave()