test_cache.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. # -*- coding: utf-8 -*-
  2. """
  3. unit tests for salt.cache
  4. """
  5. # Import Python libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import salt.cache
  8. # Import Salt libs
  9. import salt.payload
  10. from tests.support.mock import patch
  11. # Import Salt Testing libs
  12. # import integration
  13. from tests.support.unit import TestCase
  14. class CacheFunctionsTest(TestCase):
  15. """
  16. Validate the cache package functions.
  17. """
  18. def setUp(self):
  19. self.opts = {
  20. "cache": "localfs",
  21. "memcache_expire_seconds": 0,
  22. "memcache_max_items": 0,
  23. "memcache_full_cleanup": False,
  24. "memcache_debug": False,
  25. }
  26. def test_factory_cache(self):
  27. ret = salt.cache.factory(self.opts)
  28. self.assertIsInstance(ret, salt.cache.Cache)
  29. def test_factory_memcache(self):
  30. self.opts["memcache_expire_seconds"] = 10
  31. ret = salt.cache.factory(self.opts)
  32. self.assertIsInstance(ret, salt.cache.MemCache)
  33. class MemCacheTest(TestCase):
  34. """
  35. Validate Cache class methods
  36. """
  37. @patch("salt.payload.Serial")
  38. def setUp(self, serial_mock): # pylint: disable=W0221
  39. salt.cache.MemCache.data = {}
  40. self.opts = {
  41. "cache": "fake_driver",
  42. "memcache_expire_seconds": 10,
  43. "memcache_max_items": 3,
  44. "memcache_full_cleanup": False,
  45. "memcache_debug": False,
  46. }
  47. self.cache = salt.cache.factory(self.opts)
  48. @patch("salt.cache.Cache.fetch", return_value="fake_data")
  49. @patch("salt.loader.cache", return_value={})
  50. def test_fetch(self, loader_mock, cache_fetch_mock):
  51. # Fetch value, it will be kept in cache.
  52. with patch("time.time", return_value=0):
  53. ret = self.cache.fetch("bank", "key")
  54. self.assertEqual(ret, "fake_data")
  55. self.assertDictEqual(
  56. salt.cache.MemCache.data,
  57. {"fake_driver": {("bank", "key"): [0, "fake_data"]}},
  58. )
  59. cache_fetch_mock.assert_called_once_with("bank", "key")
  60. cache_fetch_mock.reset_mock()
  61. # Fetch again, cached value is used, time updated.
  62. with patch("time.time", return_value=1):
  63. ret = self.cache.fetch("bank", "key")
  64. self.assertEqual(ret, "fake_data")
  65. self.assertDictEqual(
  66. salt.cache.MemCache.data,
  67. {"fake_driver": {("bank", "key"): [1, "fake_data"]}},
  68. )
  69. cache_fetch_mock.assert_not_called()
  70. # Fetch after expire
  71. with patch("time.time", return_value=12):
  72. ret = self.cache.fetch("bank", "key")
  73. self.assertEqual(ret, "fake_data")
  74. self.assertDictEqual(
  75. salt.cache.MemCache.data,
  76. {"fake_driver": {("bank", "key"): [12, "fake_data"]}},
  77. )
  78. cache_fetch_mock.assert_called_once_with("bank", "key")
  79. cache_fetch_mock.reset_mock()
  80. @patch("salt.cache.Cache.store")
  81. @patch("salt.loader.cache", return_value={})
  82. def test_store(self, loader_mock, cache_store_mock):
  83. # Fetch value, it will be kept in cache.
  84. with patch("time.time", return_value=0):
  85. self.cache.store("bank", "key", "fake_data")
  86. self.assertDictEqual(
  87. salt.cache.MemCache.data,
  88. {"fake_driver": {("bank", "key"): [0, "fake_data"]}},
  89. )
  90. cache_store_mock.assert_called_once_with("bank", "key", "fake_data")
  91. cache_store_mock.reset_mock()
  92. # Store another value.
  93. with patch("time.time", return_value=1):
  94. self.cache.store("bank", "key2", "fake_data2")
  95. self.assertDictEqual(
  96. salt.cache.MemCache.data,
  97. {
  98. "fake_driver": {
  99. ("bank", "key"): [0, "fake_data"],
  100. ("bank", "key2"): [1, "fake_data2"],
  101. }
  102. },
  103. )
  104. cache_store_mock.assert_called_once_with("bank", "key2", "fake_data2")
  105. @patch("salt.cache.Cache.store")
  106. @patch("salt.cache.Cache.flush")
  107. @patch("salt.loader.cache", return_value={})
  108. def test_flush(self, loader_mock, cache_flush_mock, cache_store_mock):
  109. # Flush non-existing bank
  110. self.cache.flush("bank")
  111. self.assertDictEqual(salt.cache.MemCache.data, {"fake_driver": {}})
  112. cache_flush_mock.assert_called_once_with("bank", None)
  113. cache_flush_mock.reset_mock()
  114. # Flush non-existing key
  115. self.cache.flush("bank", "key")
  116. self.assertDictEqual(salt.cache.MemCache.data, {"fake_driver": {}})
  117. cache_flush_mock.assert_called_once_with("bank", "key")
  118. cache_flush_mock.reset_mock()
  119. # Flush existing key
  120. with patch("time.time", return_value=0):
  121. self.cache.store("bank", "key", "fake_data")
  122. self.assertEqual(
  123. salt.cache.MemCache.data["fake_driver"][("bank", "key")], [0, "fake_data"]
  124. )
  125. self.assertDictEqual(
  126. salt.cache.MemCache.data,
  127. {"fake_driver": {("bank", "key"): [0, "fake_data"]}},
  128. )
  129. self.cache.flush("bank", "key")
  130. self.assertDictEqual(salt.cache.MemCache.data, {"fake_driver": {}})
  131. cache_flush_mock.assert_called_once_with("bank", "key")
  132. cache_flush_mock.reset_mock()
  133. @patch("salt.cache.Cache.store")
  134. @patch("salt.loader.cache", return_value={})
  135. def test_max_items(self, loader_mock, cache_store_mock):
  136. # Put MAX=3 values
  137. with patch("time.time", return_value=0):
  138. self.cache.store("bank1", "key1", "fake_data11")
  139. with patch("time.time", return_value=1):
  140. self.cache.store("bank1", "key2", "fake_data12")
  141. with patch("time.time", return_value=2):
  142. self.cache.store("bank2", "key1", "fake_data21")
  143. self.assertDictEqual(
  144. salt.cache.MemCache.data["fake_driver"],
  145. {
  146. ("bank1", "key1"): [0, "fake_data11"],
  147. ("bank1", "key2"): [1, "fake_data12"],
  148. ("bank2", "key1"): [2, "fake_data21"],
  149. },
  150. )
  151. # Put one more and check the oldest was removed
  152. with patch("time.time", return_value=3):
  153. self.cache.store("bank2", "key2", "fake_data22")
  154. self.assertDictEqual(
  155. salt.cache.MemCache.data["fake_driver"],
  156. {
  157. ("bank1", "key2"): [1, "fake_data12"],
  158. ("bank2", "key1"): [2, "fake_data21"],
  159. ("bank2", "key2"): [3, "fake_data22"],
  160. },
  161. )
  162. @patch("salt.cache.Cache.store")
  163. @patch("salt.loader.cache", return_value={})
  164. def test_full_cleanup(self, loader_mock, cache_store_mock):
  165. # Enable full cleanup
  166. self.cache.cleanup = True
  167. # Put MAX=3 values
  168. with patch("time.time", return_value=0):
  169. self.cache.store("bank1", "key1", "fake_data11")
  170. with patch("time.time", return_value=1):
  171. self.cache.store("bank1", "key2", "fake_data12")
  172. with patch("time.time", return_value=2):
  173. self.cache.store("bank2", "key1", "fake_data21")
  174. self.assertDictEqual(
  175. salt.cache.MemCache.data["fake_driver"],
  176. {
  177. ("bank1", "key1"): [0, "fake_data11"],
  178. ("bank1", "key2"): [1, "fake_data12"],
  179. ("bank2", "key1"): [2, "fake_data21"],
  180. },
  181. )
  182. # Put one more and check all expired was removed
  183. with patch("time.time", return_value=12):
  184. self.cache.store("bank2", "key2", "fake_data22")
  185. self.assertDictEqual(
  186. salt.cache.MemCache.data["fake_driver"],
  187. {
  188. ("bank2", "key1"): [2, "fake_data21"],
  189. ("bank2", "key2"): [12, "fake_data22"],
  190. },
  191. )
  192. @patch("salt.cache.Cache.fetch", return_value="fake_data")
  193. @patch("salt.loader.cache", return_value={})
  194. def test_fetch_debug(self, loader_mock, cache_fetch_mock):
  195. # Recreate cache with debug enabled
  196. self.opts["memcache_debug"] = True
  197. self.cache = salt.cache.factory(self.opts)
  198. # Fetch 2 values (no cache hit)
  199. with patch("time.time", return_value=0):
  200. ret = self.cache.fetch("bank", "key1")
  201. with patch("time.time", return_value=1):
  202. ret = self.cache.fetch("bank", "key2")
  203. # Fetch 3 times (cache hit)
  204. with patch("time.time", return_value=2):
  205. ret = self.cache.fetch("bank", "key2")
  206. with patch("time.time", return_value=3):
  207. ret = self.cache.fetch("bank", "key1")
  208. with patch("time.time", return_value=4):
  209. ret = self.cache.fetch("bank", "key1")
  210. # Fetch an expired value (no cache hit)
  211. with patch("time.time", return_value=13):
  212. ret = self.cache.fetch("bank", "key2")
  213. # Check debug data
  214. self.assertEqual(self.cache.call, 6)
  215. self.assertEqual(self.cache.hit, 3)