test_nntp.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. from twisted.trial import unittest
  4. from twisted.news import database
  5. from twisted.news import nntp
  6. from twisted.protocols import loopback
  7. from twisted.test import proto_helpers
  8. ALL_GROUPS = ('alt.test.nntp', 0, 1, 'y'),
  9. GROUP = ('0', '1', '0', 'alt.test.nntp', 'group', 'selected')
  10. SUBSCRIPTIONS = ['alt.test.nntp', 'news.testgroup']
  11. POST_STRING = """Path: not-for-mail
  12. From: <exarkun@somehost.domain.com>
  13. Subject: a test
  14. Newsgroups: alt.test.nntp
  15. Organization:
  16. Summary:
  17. Keywords:
  18. User-Agent: tin/1.4.5-20010409 ("One More Nightmare") (UNIX) (Linux/2.4.17 (i686))
  19. this is a test
  20. .
  21. ..
  22. ...
  23. lala
  24. moo
  25. --
  26. "One World, one Web, one Program." - Microsoft(R) promotional ad
  27. "Ein Volk, ein Reich, ein Fuhrer." - Adolf Hitler
  28. --
  29. 10:56pm up 4 days, 4:42, 1 user, load average: 0.08, 0.08, 0.12
  30. """
  31. class TestNNTPClient(nntp.NNTPClient):
  32. def __init__(self):
  33. nntp.NNTPClient.__init__(self)
  34. def assertEqual(self, foo, bar):
  35. if foo != bar: raise AssertionError("%r != %r!" % (foo, bar))
  36. def connectionMade(self):
  37. nntp.NNTPClient.connectionMade(self)
  38. self.fetchSubscriptions()
  39. def gotSubscriptions(self, subscriptions):
  40. self.assertEqual(len(subscriptions), len(SUBSCRIPTIONS))
  41. for s in subscriptions:
  42. assert s in SUBSCRIPTIONS
  43. self.fetchGroups()
  44. def gotAllGroups(self, info):
  45. self.assertEqual(len(info), len(ALL_GROUPS))
  46. self.assertEqual(info[0], ALL_GROUPS[0])
  47. self.fetchGroup('alt.test.nntp')
  48. def getAllGroupsFailed(self, error):
  49. raise AssertionError("fetchGroups() failed: %s" % (error,))
  50. def gotGroup(self, info):
  51. self.assertEqual(len(info), 6)
  52. self.assertEqual(info, GROUP)
  53. self.postArticle(POST_STRING)
  54. def getSubscriptionsFailed(self, error):
  55. raise AssertionError("fetchSubscriptions() failed: %s" % (error,))
  56. def getGroupFailed(self, error):
  57. raise AssertionError("fetchGroup() failed: %s" % (error,))
  58. def postFailed(self, error):
  59. raise AssertionError("postArticle() failed: %s" % (error,))
  60. def postedOk(self):
  61. self.fetchArticle(1)
  62. def gotArticle(self, info):
  63. origBody = POST_STRING.split('\n\n')[1]
  64. newBody = info.split('\n\n', 1)[1]
  65. self.assertEqual(origBody, newBody)
  66. # We're done
  67. self.transport.loseConnection()
  68. def getArticleFailed(self, error):
  69. raise AssertionError("fetchArticle() failed: %s" % (error,))
  70. class NNTPTests(unittest.TestCase):
  71. def setUp(self):
  72. self.server = nntp.NNTPServer()
  73. self.server.factory = self
  74. self.backend = database.NewsShelf(None, 'news.db')
  75. self.backend.addGroup('alt.test.nntp', 'y')
  76. for s in SUBSCRIPTIONS:
  77. self.backend.addSubscription(s)
  78. self.transport = proto_helpers.StringTransport()
  79. self.server.makeConnection(self.transport)
  80. self.client = TestNNTPClient()
  81. def testLoopback(self):
  82. return loopback.loopbackAsync(self.server, self.client)
  83. # XXX This test is woefully incomplete. It tests the single
  84. # most common code path and nothing else. Expand it and the
  85. # test fairy will leave you a surprise.
  86. # reactor.iterate(1) # fetchGroups()
  87. # reactor.iterate(1) # fetchGroup()
  88. # reactor.iterate(1) # postArticle()
  89. def test_connectionMade(self):
  90. """
  91. When L{NNTPServer} is connected, it sends a server greeting to the
  92. client.
  93. """
  94. self.assertEqual(
  95. self.transport.value().split('\r\n'), [
  96. '200 server ready - posting allowed',
  97. ''])
  98. def test_LIST(self):
  99. """
  100. When L{NTTPServer} receives a I{LIST} command, it sends a list of news
  101. groups to the client (RFC 3977, section 7.6.1.1).
  102. """
  103. self.transport.clear()
  104. self.server.do_LIST()
  105. self.assertEqual(
  106. self.transport.value().split('\r\n'), [
  107. '215 newsgroups in form "group high low flags"',
  108. 'alt.test.nntp 0 1 y',
  109. '.',
  110. ''])
  111. def test_GROUP(self):
  112. """
  113. When L{NNTPServer} receives a I{GROUP} command, it sends a line of
  114. information about that group to the client (RFC 3977, section 6.1.1.1).
  115. """
  116. self.transport.clear()
  117. self.server.do_GROUP('alt.test.nntp')
  118. self.assertEqual(
  119. self.transport.value().split('\r\n'), [
  120. '211 0 1 0 alt.test.nntp group selected',
  121. ''])
  122. def test_LISTGROUP(self):
  123. """
  124. When L{NNTPServer} receives a I{LISTGROUP} command, it sends a list of
  125. message numbers for the messages in a particular group (RFC 3977,
  126. section 6.1.2.1).
  127. """
  128. self.transport.clear()
  129. self.server.do_LISTGROUP('alt.test.nntp')
  130. self.assertEqual(
  131. self.transport.value().split('\r\n'), [
  132. '211 list of article numbers follow',
  133. '.',
  134. ''])
  135. def test_XROVER(self):
  136. """
  137. When L{NTTPServer} receives a I{XROVER} command, it sends a list of
  138. I{References} header values for the messages in a particular group (RFC
  139. 2980, section 2.11).
  140. """
  141. self.server.do_GROUP('alt.test.nntp')
  142. self.transport.clear()
  143. self.server.do_XROVER()
  144. self.assertEqual(
  145. self.transport.value().split('\r\n'), [
  146. '221 Header follows',
  147. '.',
  148. ''])