test_skip.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import
  3. import logging
  4. from tests.support.helpers import slowTest
  5. from tests.support.unit import skipIf
  6. from tests.unit.utils.scheduler.base import SchedulerTestsBase
  7. try:
  8. import dateutil.parser
  9. HAS_DATEUTIL_PARSER = True
  10. except ImportError:
  11. HAS_DATEUTIL_PARSER = False
  12. log = logging.getLogger(__name__)
  13. @skipIf(
  14. HAS_DATEUTIL_PARSER is False, "The 'dateutil.parser' library is not available",
  15. )
  16. class SchedulerSkipTest(SchedulerTestsBase):
  17. """
  18. Validate the pkg module
  19. """
  20. def setUp(self):
  21. super(SchedulerSkipTest, self).setUp()
  22. self.schedule.opts["loop_interval"] = 1
  23. def tearDown(self):
  24. self.schedule.reset()
  25. super(SchedulerSkipTest, self).tearDown()
  26. @slowTest
  27. def test_skip(self):
  28. """
  29. verify that scheduled job is skipped at the specified time
  30. """
  31. job_name = "test_skip"
  32. job = {
  33. "schedule": {
  34. job_name: {
  35. "function": "test.ping",
  36. "when": ["11/29/2017 4pm", "11/29/2017 5pm"],
  37. }
  38. }
  39. }
  40. # Add job to schedule
  41. self.schedule.opts.update(job)
  42. run_time = dateutil.parser.parse("11/29/2017 4:00pm")
  43. self.schedule.skip_job(
  44. job_name,
  45. {
  46. "time": run_time.strftime("%Y-%m-%dT%H:%M:%S"),
  47. "time_fmt": "%Y-%m-%dT%H:%M:%S",
  48. },
  49. )
  50. # Run 11/29/2017 at 4pm
  51. self.schedule.eval(now=run_time)
  52. ret = self.schedule.job_status(job_name)
  53. self.assertNotIn("_last_run", ret)
  54. self.assertEqual(ret["_skip_reason"], "skip_explicit")
  55. self.assertEqual(ret["_skipped_time"], run_time)
  56. # Run 11/29/2017 at 5pm
  57. run_time = dateutil.parser.parse("11/29/2017 5:00pm")
  58. self.schedule.eval(now=run_time)
  59. ret = self.schedule.job_status(job_name)
  60. self.assertEqual(ret["_last_run"], run_time)
  61. @slowTest
  62. def test_skip_during_range(self):
  63. """
  64. verify that scheduled job is skipped during the specified range
  65. """
  66. job_name = "test_skip_during_range"
  67. job = {
  68. "schedule": {
  69. job_name: {
  70. "function": "test.ping",
  71. "hours": "1",
  72. "skip_during_range": {
  73. "start": "11/29/2017 2pm",
  74. "end": "11/29/2017 3pm",
  75. },
  76. }
  77. }
  78. }
  79. # Add job to schedule
  80. self.schedule.opts.update(job)
  81. # eval at 1:30pm to prime.
  82. run_time = dateutil.parser.parse("11/29/2017 1:30pm")
  83. self.schedule.eval(now=run_time)
  84. ret = self.schedule.job_status(job_name)
  85. # eval at 2:30pm, will not run during range.
  86. run_time = dateutil.parser.parse("11/29/2017 2:30pm")
  87. self.schedule.eval(now=run_time)
  88. ret = self.schedule.job_status(job_name)
  89. self.assertNotIn("_last_run", ret)
  90. self.assertEqual(ret["_skip_reason"], "in_skip_range")
  91. self.assertEqual(ret["_skipped_time"], run_time)
  92. # eval at 3:30pm, will run.
  93. run_time = dateutil.parser.parse("11/29/2017 3:30pm")
  94. self.schedule.eval(now=run_time)
  95. ret = self.schedule.job_status(job_name)
  96. self.assertEqual(ret["_last_run"], run_time)
  97. def test_skip_during_range_invalid_datestring(self):
  98. """
  99. verify that scheduled job is not not and returns the right error string
  100. """
  101. run_time = dateutil.parser.parse("11/29/2017 2:30pm")
  102. job_name1 = "skip_during_range_invalid_datestring1"
  103. job1 = {
  104. "schedule": {
  105. job_name1: {
  106. "function": "test.ping",
  107. "hours": "1",
  108. "_next_fire_time": run_time,
  109. "skip_during_range": {"start": "25pm", "end": "3pm"},
  110. }
  111. }
  112. }
  113. job_name2 = "skip_during_range_invalid_datestring2"
  114. job2 = {
  115. "schedule": {
  116. job_name2: {
  117. "function": "test.ping",
  118. "hours": "1",
  119. "_next_fire_time": run_time,
  120. "skip_during_range": {"start": "2pm", "end": "25pm"},
  121. }
  122. }
  123. }
  124. # Add job1 to schedule
  125. self.schedule.opts.update(job1)
  126. # Eval
  127. self.schedule.eval(now=run_time)
  128. # Check the first job
  129. ret = self.schedule.job_status(job_name1)
  130. _expected = (
  131. "Invalid date string for start in "
  132. "skip_during_range. Ignoring "
  133. "job {0}."
  134. ).format(job_name1)
  135. self.assertEqual(ret["_error"], _expected)
  136. # Clear out schedule
  137. self.schedule.opts["schedule"] = {}
  138. # Add job2 to schedule
  139. self.schedule.opts.update(job2)
  140. # Eval
  141. self.schedule.eval(now=run_time)
  142. # Check the second job
  143. ret = self.schedule.job_status(job_name2)
  144. _expected = (
  145. "Invalid date string for end in " "skip_during_range. Ignoring " "job {0}."
  146. ).format(job_name2)
  147. self.assertEqual(ret["_error"], _expected)
  148. @slowTest
  149. def test_skip_during_range_global(self):
  150. """
  151. verify that scheduled job is skipped during the specified range
  152. """
  153. job_name = "skip_during_range_global"
  154. job = {
  155. "schedule": {
  156. "skip_during_range": {
  157. "start": "11/29/2017 2:00pm",
  158. "end": "11/29/2017 3:00pm",
  159. },
  160. job_name: {"function": "test.ping", "hours": "1"},
  161. }
  162. }
  163. # Add job to schedule
  164. self.schedule.opts.update(job)
  165. # eval at 1:30pm to prime.
  166. run_time = dateutil.parser.parse("11/29/2017 1:30pm")
  167. self.schedule.eval(now=run_time)
  168. ret = self.schedule.job_status(job_name)
  169. # eval at 2:30pm, will not run during range.
  170. run_time = dateutil.parser.parse("11/29/2017 2:30pm")
  171. self.schedule.eval(now=run_time)
  172. ret = self.schedule.job_status(job_name)
  173. self.assertNotIn("_last_run", ret)
  174. self.assertEqual(ret["_skip_reason"], "in_skip_range")
  175. self.assertEqual(ret["_skipped_time"], run_time)
  176. # eval at 3:30pm, will run.
  177. run_time = dateutil.parser.parse("11/29/2017 3:30pm")
  178. self.schedule.eval(now=run_time)
  179. ret = self.schedule.job_status(job_name)
  180. self.assertEqual(ret["_last_run"], run_time)
  181. @slowTest
  182. def test_run_after_skip_range(self):
  183. """
  184. verify that scheduled job is skipped during the specified range
  185. """
  186. job_name = "skip_run_after_skip_range"
  187. job = {
  188. "schedule": {
  189. job_name: {
  190. "function": "test.ping",
  191. "when": "11/29/2017 2:30pm",
  192. "run_after_skip_range": True,
  193. "skip_during_range": {
  194. "start": "11/29/2017 2pm",
  195. "end": "11/29/2017 3pm",
  196. },
  197. }
  198. }
  199. }
  200. # Add job to schedule
  201. self.schedule.opts.update(job)
  202. # eval at 2:30pm, will not run during range.
  203. run_time = dateutil.parser.parse("11/29/2017 2:30pm")
  204. self.schedule.eval(now=run_time)
  205. ret = self.schedule.job_status(job_name)
  206. self.assertNotIn("_last_run", ret)
  207. self.assertEqual(ret["_skip_reason"], "in_skip_range")
  208. self.assertEqual(ret["_skipped_time"], run_time)
  209. # eval at 3:00:01pm, will run.
  210. run_time = dateutil.parser.parse("11/29/2017 3:00:01pm")
  211. self.schedule.eval(now=run_time)
  212. ret = self.schedule.job_status(job_name)
  213. self.assertEqual(ret["_last_run"], run_time)
  214. @slowTest
  215. def test_run_seconds_skip(self):
  216. """
  217. verify that scheduled job is skipped during the specified range
  218. """
  219. job_name = "run_seconds_skip"
  220. job = {"schedule": {job_name: {"function": "test.ping", "seconds": "10"}}}
  221. # Add job to schedule
  222. self.schedule.opts.update(job)
  223. # eval at 2:00pm, to prime the scheduler
  224. run_time = dateutil.parser.parse("11/29/2017 2:00pm")
  225. self.schedule.eval(now=run_time)
  226. ret = self.schedule.job_status(job_name)
  227. # eval at 2:00:10pm
  228. run_time = dateutil.parser.parse("11/29/2017 2:00:10pm")
  229. self.schedule.eval(now=run_time)
  230. ret = self.schedule.job_status(job_name)
  231. # Skip at 2:00:20pm
  232. run_time = dateutil.parser.parse("11/29/2017 2:00:20pm")
  233. self.schedule.skip_job(
  234. job_name,
  235. {
  236. "time": run_time.strftime("%Y-%m-%dT%H:%M:%S"),
  237. "time_fmt": "%Y-%m-%dT%H:%M:%S",
  238. },
  239. )
  240. self.schedule.eval(now=run_time)
  241. ret = self.schedule.job_status(job_name)
  242. self.assertIn("_next_fire_time", ret)
  243. self.assertEqual(ret["_skip_reason"], "skip_explicit")
  244. self.assertEqual(ret["_skipped_time"], run_time)
  245. # Run at 2:00:30pm
  246. run_time = dateutil.parser.parse("11/29/2017 2:00:30pm")
  247. self.schedule.eval(now=run_time)
  248. ret = self.schedule.job_status(job_name)
  249. self.assertIn("_last_run", ret)