test_mongodb.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. from __future__ import absolute_import
  2. import datetime
  3. import uuid
  4. from mock import MagicMock, Mock, patch, sentinel
  5. from nose import SkipTest
  6. from pickle import loads, dumps
  7. from celery import states
  8. from celery.backends import mongodb as module
  9. from celery.backends.mongodb import MongoBackend, Bunch, pymongo
  10. from celery.exceptions import ImproperlyConfigured
  11. from celery.tests.case import AppCase, depends_on_current_app
  12. COLLECTION = 'taskmeta_celery'
  13. TASK_ID = str(uuid.uuid1())
  14. MONGODB_HOST = 'localhost'
  15. MONGODB_PORT = 27017
  16. MONGODB_USER = 'mongo'
  17. MONGODB_PASSWORD = '1234'
  18. MONGODB_DATABASE = 'testing'
  19. MONGODB_COLLECTION = 'collection1'
  20. class test_MongoBackend(AppCase):
  21. def setup(self):
  22. if pymongo is None:
  23. raise SkipTest('pymongo is not installed.')
  24. R = self._reset = {}
  25. R['encode'], MongoBackend.encode = MongoBackend.encode, Mock()
  26. R['decode'], MongoBackend.decode = MongoBackend.decode, Mock()
  27. R['Binary'], module.Binary = module.Binary, Mock()
  28. R['datetime'], datetime.datetime = datetime.datetime, Mock()
  29. self.backend = MongoBackend(app=self.app)
  30. def teardown(self):
  31. MongoBackend.encode = self._reset['encode']
  32. MongoBackend.decode = self._reset['decode']
  33. module.Binary = self._reset['Binary']
  34. datetime.datetime = self._reset['datetime']
  35. def test_Bunch(self):
  36. x = Bunch(foo='foo', bar=2)
  37. self.assertEqual(x.foo, 'foo')
  38. self.assertEqual(x.bar, 2)
  39. def test_init_no_mongodb(self):
  40. prev, module.pymongo = module.pymongo, None
  41. try:
  42. with self.assertRaises(ImproperlyConfigured):
  43. MongoBackend(app=self.app)
  44. finally:
  45. module.pymongo = prev
  46. def test_init_no_settings(self):
  47. self.app.conf.CELERY_MONGODB_BACKEND_SETTINGS = []
  48. with self.assertRaises(ImproperlyConfigured):
  49. MongoBackend(app=self.app)
  50. def test_init_settings_is_None(self):
  51. self.app.conf.CELERY_MONGODB_BACKEND_SETTINGS = None
  52. MongoBackend(app=self.app)
  53. def test_restore_group_no_entry(self):
  54. x = MongoBackend(app=self.app)
  55. x.collection = Mock()
  56. fo = x.collection.find_one = Mock()
  57. fo.return_value = None
  58. self.assertIsNone(x._restore_group('1f3fab'))
  59. @depends_on_current_app
  60. def test_reduce(self):
  61. x = MongoBackend(app=self.app)
  62. self.assertTrue(loads(dumps(x)))
  63. def test_get_connection_connection_exists(self):
  64. with patch('pymongo.MongoClient') as mock_Connection:
  65. self.backend._connection = sentinel._connection
  66. connection = self.backend._get_connection()
  67. self.assertEqual(sentinel._connection, connection)
  68. self.assertFalse(mock_Connection.called)
  69. def test_get_connection_no_connection_host(self):
  70. with patch('pymongo.MongoClient') as mock_Connection:
  71. self.backend._connection = None
  72. self.backend.host = MONGODB_HOST
  73. self.backend.port = MONGODB_PORT
  74. mock_Connection.return_value = sentinel.connection
  75. connection = self.backend._get_connection()
  76. mock_Connection.assert_called_once_with(
  77. host='mongodb://localhost:27017', ssl=False, max_pool_size=10,
  78. auto_start_request=False)
  79. self.assertEqual(sentinel.connection, connection)
  80. def test_get_connection_no_connection_mongodb_uri(self):
  81. with patch('pymongo.MongoClient') as mock_Connection:
  82. mongodb_uri = 'mongodb://%s:%d' % (MONGODB_HOST, MONGODB_PORT)
  83. self.backend._connection = None
  84. self.backend.host = mongodb_uri
  85. mock_Connection.return_value = sentinel.connection
  86. connection = self.backend._get_connection()
  87. mock_Connection.assert_called_once_with(
  88. host=mongodb_uri, ssl=False, max_pool_size=10,
  89. auto_start_request=False)
  90. self.assertEqual(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.user = MONGODB_USER
  95. self.backend.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.user = None
  109. self.backend.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.assertEqual(self.backend._connection, None)
  122. self.backend._connection = 'not none'
  123. self.backend.process_cleanup()
  124. self.assertEqual(self.backend._connection, None)
  125. @patch('celery.backends.mongodb.MongoBackend._get_database')
  126. def test_store_result(self, mock_get_database):
  127. self.backend.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.assertEqual(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.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.assertEqual(
  151. ['status', 'task_id', 'date_done', 'traceback', 'result',
  152. 'children'],
  153. list(ret_val.keys()))
  154. @patch('celery.backends.mongodb.MongoBackend._get_database')
  155. def test_get_task_meta_for_no_result(self, mock_get_database):
  156. self.backend.taskmeta_collection = MONGODB_COLLECTION
  157. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  158. mock_collection = Mock()
  159. mock_collection.find_one.return_value = None
  160. mock_get_database.return_value = mock_database
  161. mock_database.__getitem__.return_value = mock_collection
  162. ret_val = self.backend._get_task_meta_for(sentinel.task_id)
  163. mock_get_database.assert_called_once_with()
  164. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  165. self.assertEqual({'status': states.PENDING, 'result': None}, ret_val)
  166. @patch('celery.backends.mongodb.MongoBackend._get_database')
  167. def test_save_group(self, mock_get_database):
  168. self.backend.taskmeta_collection = MONGODB_COLLECTION
  169. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  170. mock_collection = Mock()
  171. mock_get_database.return_value = mock_database
  172. mock_database.__getitem__.return_value = mock_collection
  173. ret_val = self.backend._save_group(
  174. sentinel.taskset_id, sentinel.result)
  175. mock_get_database.assert_called_once_with()
  176. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  177. mock_collection.save.assert_called_once()
  178. self.assertEqual(sentinel.result, ret_val)
  179. @patch('celery.backends.mongodb.MongoBackend._get_database')
  180. def test_restore_group(self, mock_get_database):
  181. self.backend.taskmeta_collection = MONGODB_COLLECTION
  182. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  183. mock_collection = Mock()
  184. mock_collection.find_one.return_value = MagicMock()
  185. mock_get_database.return_value = mock_database
  186. mock_database.__getitem__.return_value = mock_collection
  187. ret_val = self.backend._restore_group(sentinel.taskset_id)
  188. mock_get_database.assert_called_once_with()
  189. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  190. mock_collection.find_one.assert_called_once_with(
  191. {'_id': sentinel.taskset_id})
  192. self.assertEqual(
  193. ['date_done', 'result', 'task_id'],
  194. list(ret_val.keys()),
  195. )
  196. @patch('celery.backends.mongodb.MongoBackend._get_database')
  197. def test_delete_group(self, mock_get_database):
  198. self.backend.taskmeta_collection = MONGODB_COLLECTION
  199. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  200. mock_collection = Mock()
  201. mock_get_database.return_value = mock_database
  202. mock_database.__getitem__.return_value = mock_collection
  203. self.backend._delete_group(sentinel.taskset_id)
  204. mock_get_database.assert_called_once_with()
  205. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  206. mock_collection.remove.assert_called_once_with(
  207. {'_id': sentinel.taskset_id})
  208. @patch('celery.backends.mongodb.MongoBackend._get_database')
  209. def test_forget(self, mock_get_database):
  210. self.backend.taskmeta_collection = MONGODB_COLLECTION
  211. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  212. mock_collection = Mock()
  213. mock_get_database.return_value = mock_database
  214. mock_database.__getitem__.return_value = mock_collection
  215. self.backend._forget(sentinel.task_id)
  216. mock_get_database.assert_called_once_with()
  217. mock_database.__getitem__.assert_called_once_with(
  218. MONGODB_COLLECTION)
  219. mock_collection.remove.assert_called_once_with(
  220. {'_id': sentinel.task_id})
  221. @patch('celery.backends.mongodb.MongoBackend._get_database')
  222. def test_cleanup(self, mock_get_database):
  223. datetime.datetime = self._reset['datetime']
  224. self.backend.taskmeta_collection = MONGODB_COLLECTION
  225. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  226. mock_collection = Mock()
  227. mock_get_database.return_value = mock_database
  228. mock_database.__getitem__.return_value = mock_collection
  229. self.backend.app.now = datetime.datetime.utcnow
  230. self.backend.cleanup()
  231. mock_get_database.assert_called_once_with()
  232. mock_database.__getitem__.assert_called_once_with(
  233. MONGODB_COLLECTION)
  234. mock_collection.assert_called_once()
  235. def test_get_database_authfailure(self):
  236. x = MongoBackend(app=self.app)
  237. x._get_connection = Mock()
  238. conn = x._get_connection.return_value = {}
  239. db = conn[x.database_name] = Mock()
  240. db.authenticate.return_value = False
  241. x.user = 'jerry'
  242. x.password = 'cere4l'
  243. with self.assertRaises(ImproperlyConfigured):
  244. x._get_database()
  245. db.authenticate.assert_called_with('jerry', 'cere4l')