test_mongodb.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. from __future__ import absolute_import
  2. from __future__ import with_statement
  3. import datetime
  4. import uuid
  5. from mock import MagicMock, Mock, patch, sentinel
  6. from nose import SkipTest
  7. from pickle import loads, dumps
  8. from celery import Celery
  9. from celery import states
  10. from celery.backends import mongodb as module
  11. from celery.backends.mongodb import MongoBackend, Bunch, pymongo
  12. from celery.exceptions import ImproperlyConfigured
  13. from celery.tests.utils import AppCase
  14. COLLECTION = "taskmeta_celery"
  15. TASK_ID = str(uuid.uuid1())
  16. MONGODB_HOST = "localhost"
  17. MONGODB_PORT = 27017
  18. MONGODB_USER = "mongo"
  19. MONGODB_PASSWORD = "1234"
  20. MONGODB_DATABASE = "testing"
  21. MONGODB_COLLECTION = "collection1"
  22. class test_MongoBackend(AppCase):
  23. def setUp(self):
  24. if pymongo is None:
  25. raise SkipTest("pymongo is not installed.")
  26. R = self._reset = {}
  27. R["encode"], MongoBackend.encode = MongoBackend.encode, Mock()
  28. R["decode"], MongoBackend.decode = MongoBackend.decode, Mock()
  29. R["Binary"], module.Binary = module.Binary, Mock()
  30. R["datetime"], datetime.datetime = datetime.datetime, Mock()
  31. self.backend = MongoBackend()
  32. def tearDown(self):
  33. MongoBackend.encode = self._reset["encode"]
  34. MongoBackend.decode = self._reset["decode"]
  35. module.Binary = self._reset["Binary"]
  36. datetime.datetime = self._reset["datetime"]
  37. def test_Bunch(self):
  38. x = Bunch(foo="foo", bar=2)
  39. self.assertEqual(x.foo, "foo")
  40. self.assertEqual(x.bar, 2)
  41. def test_init_no_mongodb(self):
  42. prev, module.pymongo = module.pymongo, None
  43. try:
  44. with self.assertRaises(ImproperlyConfigured):
  45. MongoBackend()
  46. finally:
  47. module.pymongo = prev
  48. def test_init_no_settings(self):
  49. celery = Celery(set_as_current=False)
  50. celery.conf.CELERY_MONGODB_BACKEND_SETTINGS = []
  51. with self.assertRaises(ImproperlyConfigured):
  52. MongoBackend(app=celery)
  53. def test_init_settings_is_None(self):
  54. celery = Celery(set_as_current=False)
  55. celery.conf.CELERY_MONGODB_BACKEND_SETTINGS = None
  56. MongoBackend(app=celery)
  57. def test_restore_taskset_no_entry(self):
  58. x = MongoBackend()
  59. x.collection = Mock()
  60. fo = x.collection.find_one = Mock()
  61. fo.return_value = None
  62. self.assertIsNone(x._restore_taskset("1f3fab"))
  63. def test_reduce(self):
  64. x = MongoBackend()
  65. self.assertTrue(loads(dumps(x)))
  66. def test_get_connection_connection_exists(self):
  67. with patch("pymongo.connection.Connection") as mock_Connection:
  68. self.backend._connection = sentinel._connection
  69. connection = self.backend._get_connection()
  70. self.assertEquals(sentinel._connection, connection)
  71. self.assertFalse(mock_Connection.called)
  72. def test_get_connection_no_connection_host(self):
  73. with patch("pymongo.connection.Connection") as mock_Connection:
  74. self.backend._connection = None
  75. self.backend.mongodb_host = MONGODB_HOST
  76. self.backend.mongodb_port = MONGODB_PORT
  77. mock_Connection.return_value = sentinel.connection
  78. connection = self.backend._get_connection()
  79. mock_Connection.assert_called_once_with(
  80. MONGODB_HOST, MONGODB_PORT)
  81. self.assertEquals(sentinel.connection, connection)
  82. def test_get_connection_no_connection_mongodb_uri(self):
  83. with patch("pymongo.connection.Connection") as mock_Connection:
  84. mongodb_uri = "mongodb://%s:%d" % (MONGODB_HOST, MONGODB_PORT)
  85. self.backend._connection = None
  86. self.backend.mongodb_host = mongodb_uri
  87. mock_Connection.return_value = sentinel.connection
  88. connection = self.backend._get_connection()
  89. mock_Connection.assert_called_once_with(mongodb_uri)
  90. self.assertEquals(sentinel.connection, connection)
  91. @patch("celery.backends.mongodb.MongoBackend._get_connection")
  92. def test_get_database_no_existing(self, mock_get_connection):
  93. # Should really check for combinations of these two, to be complete.
  94. self.backend.mongodb_user = MONGODB_USER
  95. self.backend.mongodb_password = MONGODB_PASSWORD
  96. mock_database = Mock()
  97. mock_connection = MagicMock(spec=['__getitem__'])
  98. mock_connection.__getitem__.return_value = mock_database
  99. mock_get_connection.return_value = mock_connection
  100. database = self.backend.database
  101. self.assertTrue(database is mock_database)
  102. self.assertTrue(self.backend.__dict__["database"] is mock_database)
  103. mock_database.authenticate.assert_called_once_with(
  104. MONGODB_USER, MONGODB_PASSWORD)
  105. @patch("celery.backends.mongodb.MongoBackend._get_connection")
  106. def test_get_database_no_existing_no_auth(self, mock_get_connection):
  107. # Should really check for combinations of these two, to be complete.
  108. self.backend.mongodb_user = None
  109. self.backend.mongodb_password = None
  110. mock_database = Mock()
  111. mock_connection = MagicMock(spec=['__getitem__'])
  112. mock_connection.__getitem__.return_value = mock_database
  113. mock_get_connection.return_value = mock_connection
  114. database = self.backend.database
  115. self.assertTrue(database is mock_database)
  116. self.assertFalse(mock_database.authenticate.called)
  117. self.assertTrue(self.backend.__dict__["database"] is mock_database)
  118. def test_process_cleanup(self):
  119. self.backend._connection = None
  120. self.backend.process_cleanup()
  121. self.assertEquals(self.backend._connection, None)
  122. self.backend._connection = "not none"
  123. self.backend.process_cleanup()
  124. self.assertEquals(self.backend._connection, None)
  125. @patch("celery.backends.mongodb.MongoBackend._get_database")
  126. def test_store_result(self, mock_get_database):
  127. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  128. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  129. mock_collection = Mock()
  130. mock_get_database.return_value = mock_database
  131. mock_database.__getitem__.return_value = mock_collection
  132. ret_val = self.backend._store_result(
  133. sentinel.task_id, sentinel.result, sentinel.status)
  134. mock_get_database.assert_called_once_with()
  135. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  136. mock_collection.save.assert_called_once()
  137. self.assertEquals(sentinel.result, ret_val)
  138. @patch("celery.backends.mongodb.MongoBackend._get_database")
  139. def test_get_task_meta_for(self, mock_get_database):
  140. datetime.datetime = self._reset["datetime"]
  141. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  142. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  143. mock_collection = Mock()
  144. mock_collection.find_one.return_value = MagicMock()
  145. mock_get_database.return_value = mock_database
  146. mock_database.__getitem__.return_value = mock_collection
  147. ret_val = self.backend._get_task_meta_for(sentinel.task_id)
  148. mock_get_database.assert_called_once_with()
  149. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  150. self.assertEquals(
  151. ['status', 'date_done', 'traceback', 'result', 'task_id'],
  152. ret_val.keys())
  153. @patch("celery.backends.mongodb.MongoBackend._get_database")
  154. def test_get_task_meta_for_no_result(self, mock_get_database):
  155. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  156. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  157. mock_collection = Mock()
  158. mock_collection.find_one.return_value = None
  159. mock_get_database.return_value = mock_database
  160. mock_database.__getitem__.return_value = mock_collection
  161. ret_val = self.backend._get_task_meta_for(sentinel.task_id)
  162. mock_get_database.assert_called_once_with()
  163. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  164. self.assertEquals({"status": states.PENDING, "result": None}, ret_val)
  165. @patch("celery.backends.mongodb.MongoBackend._get_database")
  166. def test_save_taskset(self, mock_get_database):
  167. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  168. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  169. mock_collection = Mock()
  170. mock_get_database.return_value = mock_database
  171. mock_database.__getitem__.return_value = mock_collection
  172. ret_val = self.backend._save_taskset(
  173. sentinel.taskset_id, sentinel.result)
  174. mock_get_database.assert_called_once_with()
  175. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  176. mock_collection.save.assert_called_once()
  177. self.assertEquals(sentinel.result, ret_val)
  178. @patch("celery.backends.mongodb.MongoBackend._get_database")
  179. def test_restore_taskset(self, mock_get_database):
  180. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  181. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  182. mock_collection = Mock()
  183. mock_collection.find_one.return_value = MagicMock()
  184. mock_get_database.return_value = mock_database
  185. mock_database.__getitem__.return_value = mock_collection
  186. ret_val = self.backend._restore_taskset(sentinel.taskset_id)
  187. mock_get_database.assert_called_once_with()
  188. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  189. mock_collection.find_one.assert_called_once_with(
  190. {"_id": sentinel.taskset_id})
  191. self.assertEquals(['date_done', 'result', 'task_id'], ret_val.keys())
  192. @patch("celery.backends.mongodb.MongoBackend._get_database")
  193. def test_delete_taskset(self, mock_get_database):
  194. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  195. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  196. mock_collection = Mock()
  197. mock_get_database.return_value = mock_database
  198. mock_database.__getitem__.return_value = mock_collection
  199. self.backend._delete_taskset(sentinel.taskset_id)
  200. mock_get_database.assert_called_once_with()
  201. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  202. mock_collection.remove.assert_called_once_with(
  203. {"_id": sentinel.taskset_id})
  204. @patch("celery.backends.mongodb.MongoBackend._get_database")
  205. def test_forget(self, mock_get_database):
  206. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  207. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  208. mock_collection = Mock()
  209. mock_get_database.return_value = mock_database
  210. mock_database.__getitem__.return_value = mock_collection
  211. self.backend._forget(sentinel.task_id)
  212. mock_get_database.assert_called_once_with()
  213. mock_database.__getitem__.assert_called_once_with(
  214. MONGODB_COLLECTION)
  215. mock_collection.remove.assert_called_once_with(
  216. {"_id": sentinel.task_id}, safe=True)
  217. @patch("celery.backends.mongodb.MongoBackend._get_database")
  218. def test_cleanup(self, mock_get_database):
  219. datetime.datetime = self._reset["datetime"]
  220. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  221. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  222. mock_collection = Mock()
  223. mock_get_database.return_value = mock_database
  224. mock_database.__getitem__.return_value = mock_collection
  225. self.backend.app.now = datetime.datetime.utcnow
  226. self.backend.cleanup()
  227. mock_get_database.assert_called_once_with()
  228. mock_database.__getitem__.assert_called_once_with(
  229. MONGODB_COLLECTION)
  230. mock_collection.assert_called_once()
  231. def test_get_database_authfailure(self):
  232. x = MongoBackend()
  233. x._get_connection = Mock()
  234. conn = x._get_connection.return_value = {}
  235. db = conn[x.mongodb_database] = Mock()
  236. db.authenticate.return_value = False
  237. x.mongodb_user = "jerry"
  238. x.mongodb_password = "cere4l"
  239. with self.assertRaises(ImproperlyConfigured):
  240. x._get_database()
  241. db.authenticate.assert_called_with("jerry", "cere4l")