test_mongodb.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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_group_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_group('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', 'task_id', 'date_done', 'traceback', 'result',
  152. 'children'],
  153. 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(['date_done', 'result', 'task_id'], ret_val.keys())
  193. @patch('celery.backends.mongodb.MongoBackend._get_database')
  194. def test_delete_group(self, mock_get_database):
  195. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  196. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  197. mock_collection = Mock()
  198. mock_get_database.return_value = mock_database
  199. mock_database.__getitem__.return_value = mock_collection
  200. self.backend._delete_group(sentinel.taskset_id)
  201. mock_get_database.assert_called_once_with()
  202. mock_database.__getitem__.assert_called_once_with(MONGODB_COLLECTION)
  203. mock_collection.remove.assert_called_once_with(
  204. {'_id': sentinel.taskset_id})
  205. @patch('celery.backends.mongodb.MongoBackend._get_database')
  206. def test_forget(self, mock_get_database):
  207. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  208. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  209. mock_collection = Mock()
  210. mock_get_database.return_value = mock_database
  211. mock_database.__getitem__.return_value = mock_collection
  212. self.backend._forget(sentinel.task_id)
  213. mock_get_database.assert_called_once_with()
  214. mock_database.__getitem__.assert_called_once_with(
  215. MONGODB_COLLECTION)
  216. mock_collection.remove.assert_called_once_with(
  217. {'_id': sentinel.task_id}, safe=True)
  218. @patch('celery.backends.mongodb.MongoBackend._get_database')
  219. def test_cleanup(self, mock_get_database):
  220. datetime.datetime = self._reset['datetime']
  221. self.backend.mongodb_taskmeta_collection = MONGODB_COLLECTION
  222. mock_database = MagicMock(spec=['__getitem__', '__setitem__'])
  223. mock_collection = Mock()
  224. mock_get_database.return_value = mock_database
  225. mock_database.__getitem__.return_value = mock_collection
  226. self.backend.app.now = datetime.datetime.utcnow
  227. self.backend.cleanup()
  228. mock_get_database.assert_called_once_with()
  229. mock_database.__getitem__.assert_called_once_with(
  230. MONGODB_COLLECTION)
  231. mock_collection.assert_called_once()
  232. def test_get_database_authfailure(self):
  233. x = MongoBackend()
  234. x._get_connection = Mock()
  235. conn = x._get_connection.return_value = {}
  236. db = conn[x.mongodb_database] = Mock()
  237. db.authenticate.return_value = False
  238. x.mongodb_user = 'jerry'
  239. x.mongodb_password = 'cere4l'
  240. with self.assertRaises(ImproperlyConfigured):
  241. x._get_database()
  242. db.authenticate.assert_called_with('jerry', 'cere4l')