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 Celery
  8. from celery import states
  9. from celery.backends import mongodb as module
  10. from celery.backends.mongodb import MongoBackend, Bunch, pymongo
  11. from celery.exceptions import ImproperlyConfigured
  12. from celery.tests.utils import AppCase
  13. COLLECTION = 'taskmeta_celery'
  14. TASK_ID = str(uuid.uuid1())
  15. MONGODB_HOST = 'localhost'
  16. MONGODB_PORT = 27017
  17. MONGODB_USER = 'mongo'
  18. MONGODB_PASSWORD = '1234'
  19. MONGODB_DATABASE = 'testing'
  20. MONGODB_COLLECTION = 'collection1'
  21. class test_MongoBackend(AppCase):
  22. def setUp(self):
  23. if pymongo is None:
  24. raise SkipTest('pymongo is not installed.')
  25. R = self._reset = {}
  26. R['encode'], MongoBackend.encode = MongoBackend.encode, Mock()
  27. R['decode'], MongoBackend.decode = MongoBackend.decode, Mock()
  28. R['Binary'], module.Binary = module.Binary, Mock()
  29. R['datetime'], datetime.datetime = datetime.datetime, Mock()
  30. self.backend = MongoBackend()
  31. def tearDown(self):
  32. MongoBackend.encode = self._reset['encode']
  33. MongoBackend.decode = self._reset['decode']
  34. module.Binary = self._reset['Binary']
  35. datetime.datetime = self._reset['datetime']
  36. def test_Bunch(self):
  37. x = Bunch(foo='foo', bar=2)
  38. self.assertEqual(x.foo, 'foo')
  39. self.assertEqual(x.bar, 2)
  40. def test_init_no_mongodb(self):
  41. prev, module.pymongo = module.pymongo, None
  42. try:
  43. with self.assertRaises(ImproperlyConfigured):
  44. MongoBackend()
  45. finally:
  46. module.pymongo = prev
  47. def test_init_no_settings(self):
  48. celery = Celery(set_as_current=False)
  49. celery.conf.CELERY_MONGODB_BACKEND_SETTINGS = []
  50. with self.assertRaises(ImproperlyConfigured):
  51. MongoBackend(app=celery)
  52. def test_init_settings_is_None(self):
  53. celery = Celery(set_as_current=False)
  54. celery.conf.CELERY_MONGODB_BACKEND_SETTINGS = None
  55. MongoBackend(app=celery)
  56. def test_restore_group_no_entry(self):
  57. x = MongoBackend()
  58. x.collection = Mock()
  59. fo = x.collection.find_one = Mock()
  60. fo.return_value = None
  61. self.assertIsNone(x._restore_group('1f3fab'))
  62. def test_reduce(self):
  63. x = MongoBackend()
  64. self.assertTrue(loads(dumps(x)))
  65. def test_get_connection_connection_exists(self):
  66. with patch('pymongo.connection.Connection') as mock_Connection:
  67. self.backend._connection = sentinel._connection
  68. connection = self.backend._get_connection()
  69. self.assertEquals(sentinel._connection, connection)
  70. self.assertFalse(mock_Connection.called)
  71. def test_get_connection_no_connection_host(self):
  72. with patch('pymongo.connection.Connection') as mock_Connection:
  73. self.backend._connection = None
  74. self.backend.mongodb_host = MONGODB_HOST
  75. self.backend.mongodb_port = MONGODB_PORT
  76. mock_Connection.return_value = sentinel.connection
  77. connection = self.backend._get_connection()
  78. mock_Connection.assert_called_once_with(
  79. MONGODB_HOST, MONGODB_PORT, ssl=False, max_pool_size=10)
  80. self.assertEquals(sentinel.connection, connection)
  81. def test_get_connection_no_connection_mongodb_uri(self):
  82. with patch('pymongo.connection.Connection') as mock_Connection:
  83. mongodb_uri = 'mongodb://%s:%d' % (MONGODB_HOST, MONGODB_PORT)
  84. self.backend._connection = None
  85. self.backend.mongodb_host = mongodb_uri
  86. mock_Connection.return_value = sentinel.connection
  87. connection = self.backend._get_connection()
  88. mock_Connection.assert_called_once_with(
  89. mongodb_uri, ssl=False, max_pool_size=10)
  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', '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.mongodb_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.assertEquals({'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.mongodb_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.assertEquals(sentinel.result, ret_val)
  179. @patch('celery.backends.mongodb.MongoBackend._get_database')
  180. def test_restore_group(self, mock_get_database):
  181. self.backend.mongodb_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.assertEquals(
  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.mongodb_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.mongodb_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.mongodb_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()
  237. x._get_connection = Mock()
  238. conn = x._get_connection.return_value = {}
  239. db = conn[x.mongodb_database] = Mock()
  240. db.authenticate.return_value = False
  241. x.mongodb_user = 'jerry'
  242. x.mongodb_password = 'cere4l'
  243. with self.assertRaises(ImproperlyConfigured):
  244. x._get_database()
  245. db.authenticate.assert_called_with('jerry', 'cere4l')