PageRenderTime 37ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/hyperkitty/tests/_test_caching.py

https://gitlab.com/Acidburn0zzz/hyperkitty
Python | 237 lines | 177 code | 25 blank | 35 comment | 5 complexity | 03646a3e52a6bc18760deab712838aad MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. # flake8: noqa
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import unittest
  5. import datetime
  6. import uuid
  7. from six.moves.urllib.error import HTTPError
  8. from mock import Mock
  9. from mailman.email.message import Message
  10. from mailman.interfaces.archiver import ArchivePolicy
  11. #import kittystore.utils
  12. #from kittystore import get_store
  13. #from kittystore.caching import mailman_user
  14. #from kittystore.test import FakeList, SettingsModule
  15. class ListCacheTestCase(unittest.TestCase):
  16. def setUp(self):
  17. self.store = get_store(SettingsModule(), auto_create=True)
  18. kittystore.utils.MM_CLIENT = Mock()
  19. def tearDown(self):
  20. self.store.close()
  21. kittystore.utils.MM_CLIENT = None
  22. def test_properties_on_new_message(self):
  23. ml = FakeList("example-list")
  24. ml.display_name = u"name 1"
  25. ml.subject_prefix = u"[prefix 1]"
  26. ml.description = u"desc 1"
  27. kittystore.utils.MM_CLIENT.get_list.side_effect = lambda n: ml
  28. msg = Message()
  29. msg["From"] = "dummy@example.com"
  30. msg["Message-ID"] = "<dummy>"
  31. msg.set_payload("Dummy message")
  32. self.store.add_to_list("example-list", msg)
  33. ml_db = self.store.get_lists()[0]
  34. self.assertEqual(ml_db.display_name, "name 1")
  35. self.assertEqual(ml_db.subject_prefix, "[prefix 1]")
  36. ml.display_name = u"name 2"
  37. ml.subject_prefix = u"[prefix 2]"
  38. ml.description = u"desc 2"
  39. ml.archive_policy = "private"
  40. msg.replace_header("Message-ID", "<dummy2>")
  41. self.store.add_to_list("example-list", msg)
  42. ml_db = self.store.get_lists()[0]
  43. #ml_db = self.store.db.find(List).one()
  44. self.assertEqual(ml_db.display_name, "name 2")
  45. self.assertEqual(ml_db.subject_prefix, "[prefix 2]")
  46. self.assertEqual(ml_db.description, "desc 2")
  47. self.assertEqual(ml_db.archive_policy, ArchivePolicy.private)
  48. def test_on_old_message(self):
  49. kittystore.utils.MM_CLIENT = None
  50. olddate = datetime.datetime.utcnow() - datetime.timedelta(days=40)
  51. msg = Message()
  52. msg["From"] = "dummy@example.com"
  53. msg["Message-ID"] = "<dummy>"
  54. msg["Date"] = olddate.isoformat()
  55. msg.set_payload("Dummy message")
  56. self.store.add_to_list("example-list", msg)
  57. ml_db = self.store.get_lists()[0]
  58. self.assertEqual(ml_db.recent_participants_count, 0)
  59. self.assertEqual(ml_db.recent_threads_count, 0)
  60. class FakeMMUser(object):
  61. user_id = None
  62. class UserIdCacheTestCase(unittest.TestCase):
  63. def setUp(self):
  64. self.store = get_store(SettingsModule(), auto_create=True)#, debug=True)
  65. self.mm_client = Mock()
  66. mailman_user._MAILMAN_CLIENT = self.mm_client
  67. self.mm_client.get_user.side_effect = HTTPError(
  68. None, 404, "dummy", {}, None)
  69. def tearDown(self):
  70. self.store.close()
  71. mailman_user._MAILMAN_CLIENT = None
  72. def test_on_new_message_userid(self):
  73. # Check that the user_id is set on a new message
  74. msg = Message()
  75. msg["From"] = "dummy@example.com"
  76. msg["Message-ID"] = "<dummy>"
  77. msg.set_payload("Dummy message")
  78. # setup Mailman's reply
  79. new_user_id = FakeMMUser()
  80. uid = uuid.uuid1()
  81. new_user_id.user_id = uid.int
  82. self.mm_client.get_user.side_effect = lambda addr: new_user_id
  83. # check the User does not exist yet
  84. self.assertEqual(0,
  85. self.store.get_message_count_by_user_id(uid))
  86. # do the test and check
  87. self.store.add_to_list("example-list", msg)
  88. dbmsg = self.store.get_message_by_id_from_list(
  89. "example-list", "dummy")
  90. self.assertEqual(dbmsg.sender.user_id, uid)
  91. self.assertTrue(dbmsg.sender.user is not None,
  92. "A 'User' instance was not created")
  93. self.assertEqual(dbmsg.sender.user.id, uid)
  94. self.assertEqual(1,
  95. self.store.get_message_count_by_user_id(uid))
  96. self.assertEqual(self.store.get_users_count(), 1)
  97. def test_on_new_message_no_reply_from_mailman(self):
  98. # Check that the user_id is set on a new message
  99. msg = Message()
  100. msg["From"] = "dummy@example.com"
  101. msg["Message-ID"] = "<dummy>"
  102. msg.set_payload("Dummy message")
  103. self.store.add_to_list("example-list", msg)
  104. dbmsg = self.store.get_message_by_id_from_list(
  105. "example-list", "dummy")
  106. self.assertEqual(dbmsg.sender.user_id, None)
  107. def test_sync_mailman_user(self):
  108. # Check that the user_id is set when sync_mailman_user is run
  109. msg = Message()
  110. msg["From"] = "dummy@example.com"
  111. msg["Message-ID"] = "<dummy>"
  112. msg.set_payload("Dummy message")
  113. self.store.add_to_list("example-list", msg)
  114. dbmsg = self.store.get_message_by_id_from_list(
  115. "example-list", "dummy")
  116. self.assertEqual(dbmsg.sender.user_id, None)
  117. # setup Mailman's reply
  118. uid = uuid.uuid1()
  119. new_user_id = FakeMMUser()
  120. new_user_id.user_id = uid.int
  121. self.mm_client.get_user.side_effect = lambda addr: new_user_id
  122. # do the test and check
  123. mailman_user.sync_mailman_user(self.store)
  124. #dbmsg = self.store.get_message_by_id_from_list(
  125. # "example-list", "dummy")
  126. self.assertEqual(dbmsg.sender.user_id, uid)
  127. self.assertTrue(dbmsg.sender.user is not None,
  128. "A 'User' instance was not created")
  129. self.assertEqual(dbmsg.sender.user.id, uid)
  130. self.assertEqual(1,
  131. self.store.get_message_count_by_user_id(uid))
  132. def test_on_new_message_bad_reply_from_mailman(self):
  133. # Check that errors from mailmanclient are handled gracefully
  134. self.mm_client.get_user.side_effect = ValueError
  135. msg = Message()
  136. msg["From"] = "dummy@example.com"
  137. msg["Message-ID"] = "<dummy>"
  138. msg.set_payload("Dummy message")
  139. try:
  140. self.store.add_to_list("example-list", msg)
  141. except ValueError as e:
  142. self.fail("Errors from mailmanclient should be handled gracefully")
  143. dbmsg = self.store.get_message_by_id_from_list(
  144. "example-list", "dummy")
  145. self.assertEqual(dbmsg.sender.user_id, None)
  146. class TestNotifyStore(unittest.TestCase):
  147. def setUp(self):
  148. self.store = get_sa_store(SettingsModule(), auto_create=True)
  149. self.store.db.cache.get_or_create = Mock()
  150. self.store.db.cache.get_or_create.side_effect = lambda *a, **kw: a[1]()
  151. self.store.db.cache.set = Mock()
  152. # cache.delete() will be called if the cache is invalidated
  153. self.store.db.cache.delete = Mock()
  154. def tearDown(self):
  155. self.store.close()
  156. def test_on_new_message_invalidate(self):
  157. # Check that the cache is invalidated on new message
  158. msg = Message()
  159. msg["From"] = "dummy@example.com"
  160. msg["Message-ID"] = "<dummy>"
  161. msg.set_payload("Dummy message")
  162. today = datetime.datetime.utcnow().date() # don't use datetime.date.today(), we need UTC
  163. self.store.add_to_list("example-list", msg)
  164. # calls to cache.delete() -- invalidation
  165. delete_args = [ call[0][0] for call in
  166. self.store.db.cache.delete.call_args_list ]
  167. #from pprint import pprint; pprint(delete_args)
  168. self.assertEqual(set(delete_args), set([
  169. u'list:example-list:recent_participants_count',
  170. u'list:example-list:recent_threads_count',
  171. u'list:example-list:participants_count:%d:%d' % (today.year, today.month),
  172. u'list:example-list:thread:QKODQBCADMDSP5YPOPKECXQWEQAMXZL3:emails_count',
  173. u'list:example-list:thread:QKODQBCADMDSP5YPOPKECXQWEQAMXZL3:participants_count'
  174. ]))
  175. # calls to cache.get_or_create() -- repopulation
  176. goc_args = [ call[0][0] for call in
  177. self.store.db.cache.get_or_create.call_args_list ]
  178. #from pprint import pprint; pprint(goc_args)
  179. self.assertEqual(set(goc_args), set([
  180. u'list:example-list:recent_participants_count',
  181. u'list:example-list:recent_threads_count',
  182. u'list:example-list:participants_count:%d:%d' % (today.year, today.month),
  183. u'list:example-list:threads_count:%d:%d' % (today.year, today.month),
  184. u'list:example-list:thread:QKODQBCADMDSP5YPOPKECXQWEQAMXZL3:emails_count',
  185. u'list:example-list:thread:QKODQBCADMDSP5YPOPKECXQWEQAMXZL3:participants_count',
  186. u'list:example-list:thread:QKODQBCADMDSP5YPOPKECXQWEQAMXZL3:starting_email_id',
  187. ]))
  188. #self.assertEqual(l.recent_participants_count, 1)
  189. #self.assertEqual(l.recent_threads_count, 1)
  190. #msg.replace_header("Message-ID", "<dummy2>")
  191. #self.store.add_to_list("example-list", msg)
  192. #self.assertEqual(l.recent_participants_count, 1)
  193. #self.assertEqual(l.recent_threads_count, 2)
  194. def test_on_new_thread_invalidate(self):
  195. # Check that the cache is invalidated on new message
  196. msg = Message()
  197. msg["From"] = "dummy@example.com"
  198. msg["Message-ID"] = "<dummy>"
  199. msg.set_payload("Dummy message")
  200. self.store.add_to_list("example-list", msg)
  201. msg.replace_header("Message-ID", "<dummy2>")
  202. msg["In-Reply-To"] = "<dummy>"
  203. self.store.add_to_list("example-list", msg)
  204. call_args = [ call[0][0] for call in self.store.db.cache.set.call_args_list ]
  205. # we have duplicates because both the Storm and the SQLAlchemy model
  206. # subscribe to the event, so we must deduplicate
  207. call_args = set(call_args)
  208. #from pprint import pprint; pprint(call_args)
  209. #print(repr(call_args))
  210. self.assertEqual(call_args, set([
  211. u'list:example-list:thread:QKODQBCADMDSP5YPOPKECXQWEQAMXZL3:subject'
  212. ]))