test_schedules.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. from __future__ import absolute_import
  2. import time
  3. from contextlib import contextmanager
  4. from datetime import datetime, timedelta
  5. from pickle import dumps, loads
  6. from nose import SkipTest
  7. from celery.five import items
  8. from celery.schedules import ParseException, crontab, crontab_parser
  9. from celery.tests.case import AppCase
  10. @contextmanager
  11. def patch_crontab_nowfun(cls, retval):
  12. prev_nowfun = cls.nowfun
  13. cls.nowfun = lambda: retval
  14. try:
  15. yield
  16. finally:
  17. cls.nowfun = prev_nowfun
  18. class test_crontab_parser(AppCase):
  19. def crontab(self, *args, **kwargs):
  20. return crontab(*args, **dict(kwargs, app=self.app))
  21. def test_crontab_reduce(self):
  22. self.assertTrue(loads(dumps(self.crontab('*'))))
  23. def test_range_steps_not_enough(self):
  24. with self.assertRaises(crontab_parser.ParseException):
  25. crontab_parser(24)._range_steps([1])
  26. def test_parse_star(self):
  27. self.assertEqual(crontab_parser(24).parse('*'), set(range(24)))
  28. self.assertEqual(crontab_parser(60).parse('*'), set(range(60)))
  29. self.assertEqual(crontab_parser(7).parse('*'), set(range(7)))
  30. self.assertEqual(crontab_parser(31, 1).parse('*'),
  31. set(range(1, 31 + 1)))
  32. self.assertEqual(crontab_parser(12, 1).parse('*'),
  33. set(range(1, 12 + 1)))
  34. def test_parse_range(self):
  35. self.assertEqual(crontab_parser(60).parse('1-10'),
  36. set(range(1, 10 + 1)))
  37. self.assertEqual(crontab_parser(24).parse('0-20'),
  38. set(range(0, 20 + 1)))
  39. self.assertEqual(crontab_parser().parse('2-10'),
  40. set(range(2, 10 + 1)))
  41. self.assertEqual(crontab_parser(60, 1).parse('1-10'),
  42. set(range(1, 10 + 1)))
  43. def test_parse_range_wraps(self):
  44. self.assertEqual(crontab_parser(12).parse('11-1'),
  45. set([11, 0, 1]))
  46. self.assertEqual(crontab_parser(60, 1).parse('2-1'),
  47. set(range(1, 60 + 1)))
  48. def test_parse_groups(self):
  49. self.assertEqual(crontab_parser().parse('1,2,3,4'),
  50. set([1, 2, 3, 4]))
  51. self.assertEqual(crontab_parser().parse('0,15,30,45'),
  52. set([0, 15, 30, 45]))
  53. self.assertEqual(crontab_parser(min_=1).parse('1,2,3,4'),
  54. set([1, 2, 3, 4]))
  55. def test_parse_steps(self):
  56. self.assertEqual(crontab_parser(8).parse('*/2'),
  57. set([0, 2, 4, 6]))
  58. self.assertEqual(crontab_parser().parse('*/2'),
  59. set(i * 2 for i in range(30)))
  60. self.assertEqual(crontab_parser().parse('*/3'),
  61. set(i * 3 for i in range(20)))
  62. self.assertEqual(crontab_parser(8, 1).parse('*/2'),
  63. set([1, 3, 5, 7]))
  64. self.assertEqual(crontab_parser(min_=1).parse('*/2'),
  65. set(i * 2 + 1 for i in range(30)))
  66. self.assertEqual(crontab_parser(min_=1).parse('*/3'),
  67. set(i * 3 + 1 for i in range(20)))
  68. def test_parse_composite(self):
  69. self.assertEqual(crontab_parser(8).parse('*/2'), set([0, 2, 4, 6]))
  70. self.assertEqual(crontab_parser().parse('2-9/5'), set([2, 7]))
  71. self.assertEqual(crontab_parser().parse('2-10/5'), set([2, 7]))
  72. self.assertEqual(
  73. crontab_parser(min_=1).parse('55-5/3'),
  74. set([55, 58, 1, 4]),
  75. )
  76. self.assertEqual(crontab_parser().parse('2-11/5,3'), set([2, 3, 7]))
  77. self.assertEqual(
  78. crontab_parser().parse('2-4/3,*/5,0-21/4'),
  79. set([0, 2, 4, 5, 8, 10, 12, 15, 16,
  80. 20, 25, 30, 35, 40, 45, 50, 55]),
  81. )
  82. self.assertEqual(
  83. crontab_parser().parse('1-9/2'),
  84. set([1, 3, 5, 7, 9]),
  85. )
  86. self.assertEqual(crontab_parser(8, 1).parse('*/2'), set([1, 3, 5, 7]))
  87. self.assertEqual(crontab_parser(min_=1).parse('2-9/5'), set([2, 7]))
  88. self.assertEqual(crontab_parser(min_=1).parse('2-10/5'), set([2, 7]))
  89. self.assertEqual(
  90. crontab_parser(min_=1).parse('2-11/5,3'),
  91. set([2, 3, 7]),
  92. )
  93. self.assertEqual(
  94. crontab_parser(min_=1).parse('2-4/3,*/5,1-21/4'),
  95. set([1, 2, 5, 6, 9, 11, 13, 16, 17,
  96. 21, 26, 31, 36, 41, 46, 51, 56]),
  97. )
  98. self.assertEqual(
  99. crontab_parser(min_=1).parse('1-9/2'),
  100. set([1, 3, 5, 7, 9]),
  101. )
  102. def test_parse_errors_on_empty_string(self):
  103. with self.assertRaises(ParseException):
  104. crontab_parser(60).parse('')
  105. def test_parse_errors_on_empty_group(self):
  106. with self.assertRaises(ParseException):
  107. crontab_parser(60).parse('1,,2')
  108. def test_parse_errors_on_empty_steps(self):
  109. with self.assertRaises(ParseException):
  110. crontab_parser(60).parse('*/')
  111. def test_parse_errors_on_negative_number(self):
  112. with self.assertRaises(ParseException):
  113. crontab_parser(60).parse('-20')
  114. def test_parse_errors_on_lt_min(self):
  115. crontab_parser(min_=1).parse('1')
  116. with self.assertRaises(ValueError):
  117. crontab_parser(12, 1).parse('0')
  118. with self.assertRaises(ValueError):
  119. crontab_parser(24, 1).parse('12-0')
  120. def test_parse_errors_on_gt_max(self):
  121. crontab_parser(1).parse('0')
  122. with self.assertRaises(ValueError):
  123. crontab_parser(1).parse('1')
  124. with self.assertRaises(ValueError):
  125. crontab_parser(60).parse('61-0')
  126. def test_expand_cronspec_eats_iterables(self):
  127. self.assertEqual(
  128. crontab._expand_cronspec(iter([1, 2, 3]), 100),
  129. set([1, 2, 3]),
  130. )
  131. self.assertEqual(
  132. crontab._expand_cronspec(iter([1, 2, 3]), 100, 1),
  133. set([1, 2, 3]),
  134. )
  135. def test_expand_cronspec_invalid_type(self):
  136. with self.assertRaises(TypeError):
  137. crontab._expand_cronspec(object(), 100)
  138. def test_repr(self):
  139. self.assertIn('*', repr(self.crontab('*')))
  140. def test_eq(self):
  141. self.assertEqual(
  142. self.crontab(day_of_week='1, 2'),
  143. self.crontab(day_of_week='1-2'),
  144. )
  145. self.assertEqual(
  146. self.crontab(day_of_month='1, 16, 31'),
  147. self.crontab(day_of_month='*/15'),
  148. )
  149. self.assertEqual(
  150. self.crontab(minute='1', hour='2', day_of_week='5',
  151. day_of_month='10', month_of_year='5'),
  152. self.crontab(minute='1', hour='2', day_of_week='5',
  153. day_of_month='10', month_of_year='5'),
  154. )
  155. self.assertNotEqual(crontab(minute='1'), crontab(minute='2'))
  156. self.assertNotEqual(
  157. self.crontab(month_of_year='1'),
  158. self.crontab(month_of_year='2'),
  159. )
  160. self.assertFalse(object() == self.crontab(minute='1'))
  161. self.assertFalse(self.crontab(minute='1') == object())
  162. class test_crontab_remaining_estimate(AppCase):
  163. def crontab(self, *args, **kwargs):
  164. return crontab(*args, **dict(kwargs, app=self.app))
  165. def next_ocurrance(self, crontab, now):
  166. crontab.nowfun = lambda: now
  167. return now + crontab.remaining_estimate(now)
  168. def test_next_minute(self):
  169. next = self.next_ocurrance(
  170. self.crontab(), datetime(2010, 9, 11, 14, 30, 15),
  171. )
  172. self.assertEqual(next, datetime(2010, 9, 11, 14, 31))
  173. def test_not_next_minute(self):
  174. next = self.next_ocurrance(
  175. self.crontab(), datetime(2010, 9, 11, 14, 59, 15),
  176. )
  177. self.assertEqual(next, datetime(2010, 9, 11, 15, 0))
  178. def test_this_hour(self):
  179. next = self.next_ocurrance(
  180. self.crontab(minute=[5, 42]), datetime(2010, 9, 11, 14, 30, 15),
  181. )
  182. self.assertEqual(next, datetime(2010, 9, 11, 14, 42))
  183. def test_not_this_hour(self):
  184. next = self.next_ocurrance(
  185. self.crontab(minute=[5, 10, 15]),
  186. datetime(2010, 9, 11, 14, 30, 15),
  187. )
  188. self.assertEqual(next, datetime(2010, 9, 11, 15, 5))
  189. def test_today(self):
  190. next = self.next_ocurrance(
  191. self.crontab(minute=[5, 42], hour=[12, 17]),
  192. datetime(2010, 9, 11, 14, 30, 15),
  193. )
  194. self.assertEqual(next, datetime(2010, 9, 11, 17, 5))
  195. def test_not_today(self):
  196. next = self.next_ocurrance(
  197. self.crontab(minute=[5, 42], hour=[12]),
  198. datetime(2010, 9, 11, 14, 30, 15),
  199. )
  200. self.assertEqual(next, datetime(2010, 9, 12, 12, 5))
  201. def test_weekday(self):
  202. next = self.next_ocurrance(
  203. self.crontab(minute=30, hour=14, day_of_week='sat'),
  204. datetime(2010, 9, 11, 14, 30, 15),
  205. )
  206. self.assertEqual(next, datetime(2010, 9, 18, 14, 30))
  207. def test_not_weekday(self):
  208. next = self.next_ocurrance(
  209. self.crontab(minute=[5, 42], day_of_week='mon-fri'),
  210. datetime(2010, 9, 11, 14, 30, 15),
  211. )
  212. self.assertEqual(next, datetime(2010, 9, 13, 0, 5))
  213. def test_monthday(self):
  214. next = self.next_ocurrance(
  215. self.crontab(minute=30, hour=14, day_of_month=18),
  216. datetime(2010, 9, 11, 14, 30, 15),
  217. )
  218. self.assertEqual(next, datetime(2010, 9, 18, 14, 30))
  219. def test_not_monthday(self):
  220. next = self.next_ocurrance(
  221. self.crontab(minute=[5, 42], day_of_month=29),
  222. datetime(2010, 1, 22, 14, 30, 15),
  223. )
  224. self.assertEqual(next, datetime(2010, 1, 29, 0, 5))
  225. def test_weekday_monthday(self):
  226. next = self.next_ocurrance(
  227. self.crontab(minute=30, hour=14,
  228. day_of_week='mon', day_of_month=18),
  229. datetime(2010, 1, 18, 14, 30, 15),
  230. )
  231. self.assertEqual(next, datetime(2010, 10, 18, 14, 30))
  232. def test_monthday_not_weekday(self):
  233. next = self.next_ocurrance(
  234. self.crontab(minute=[5, 42], day_of_week='sat', day_of_month=29),
  235. datetime(2010, 1, 29, 0, 5, 15),
  236. )
  237. self.assertEqual(next, datetime(2010, 5, 29, 0, 5))
  238. def test_weekday_not_monthday(self):
  239. next = self.next_ocurrance(
  240. self.crontab(minute=[5, 42], day_of_week='mon', day_of_month=18),
  241. datetime(2010, 1, 11, 0, 5, 15),
  242. )
  243. self.assertEqual(next, datetime(2010, 1, 18, 0, 5))
  244. def test_not_weekday_not_monthday(self):
  245. next = self.next_ocurrance(
  246. self.crontab(minute=[5, 42], day_of_week='mon', day_of_month=18),
  247. datetime(2010, 1, 10, 0, 5, 15),
  248. )
  249. self.assertEqual(next, datetime(2010, 1, 18, 0, 5))
  250. def test_leapday(self):
  251. next = self.next_ocurrance(
  252. self.crontab(minute=30, hour=14, day_of_month=29),
  253. datetime(2012, 1, 29, 14, 30, 15),
  254. )
  255. self.assertEqual(next, datetime(2012, 2, 29, 14, 30))
  256. def test_not_leapday(self):
  257. next = self.next_ocurrance(
  258. self.crontab(minute=30, hour=14, day_of_month=29),
  259. datetime(2010, 1, 29, 14, 30, 15),
  260. )
  261. self.assertEqual(next, datetime(2010, 3, 29, 14, 30))
  262. def test_weekmonthdayyear(self):
  263. next = self.next_ocurrance(
  264. self.crontab(minute=30, hour=14, day_of_week='fri',
  265. day_of_month=29, month_of_year=1),
  266. datetime(2010, 1, 22, 14, 30, 15),
  267. )
  268. self.assertEqual(next, datetime(2010, 1, 29, 14, 30))
  269. def test_monthdayyear_not_week(self):
  270. next = self.next_ocurrance(
  271. self.crontab(minute=[5, 42], day_of_week='wed,thu',
  272. day_of_month=29, month_of_year='1,4,7'),
  273. datetime(2010, 1, 29, 14, 30, 15),
  274. )
  275. self.assertEqual(next, datetime(2010, 4, 29, 0, 5))
  276. def test_weekdaymonthyear_not_monthday(self):
  277. next = self.next_ocurrance(
  278. self.crontab(minute=30, hour=14, day_of_week='fri',
  279. day_of_month=29, month_of_year='1-10'),
  280. datetime(2010, 1, 29, 14, 30, 15),
  281. )
  282. self.assertEqual(next, datetime(2010, 10, 29, 14, 30))
  283. def test_weekmonthday_not_monthyear(self):
  284. next = self.next_ocurrance(
  285. self.crontab(minute=[5, 42], day_of_week='fri',
  286. day_of_month=29, month_of_year='2-10'),
  287. datetime(2010, 1, 29, 14, 30, 15),
  288. )
  289. self.assertEqual(next, datetime(2010, 10, 29, 0, 5))
  290. def test_weekday_not_monthdayyear(self):
  291. next = self.next_ocurrance(
  292. self.crontab(minute=[5, 42], day_of_week='mon',
  293. day_of_month=18, month_of_year='2-10'),
  294. datetime(2010, 1, 11, 0, 5, 15),
  295. )
  296. self.assertEqual(next, datetime(2010, 10, 18, 0, 5))
  297. def test_monthday_not_weekdaymonthyear(self):
  298. next = self.next_ocurrance(
  299. self.crontab(minute=[5, 42], day_of_week='mon',
  300. day_of_month=29, month_of_year='2-4'),
  301. datetime(2010, 1, 29, 0, 5, 15),
  302. )
  303. self.assertEqual(next, datetime(2010, 3, 29, 0, 5))
  304. def test_monthyear_not_weekmonthday(self):
  305. next = self.next_ocurrance(
  306. self.crontab(minute=[5, 42], day_of_week='mon',
  307. day_of_month=29, month_of_year='2-4'),
  308. datetime(2010, 2, 28, 0, 5, 15),
  309. )
  310. self.assertEqual(next, datetime(2010, 3, 29, 0, 5))
  311. def test_not_weekmonthdayyear(self):
  312. next = self.next_ocurrance(
  313. self.crontab(minute=[5, 42], day_of_week='fri,sat',
  314. day_of_month=29, month_of_year='2-10'),
  315. datetime(2010, 1, 28, 14, 30, 15),
  316. )
  317. self.assertEqual(next, datetime(2010, 5, 29, 0, 5))
  318. class test_crontab_is_due(AppCase):
  319. def getnow(self):
  320. return self.app.now()
  321. def setup(self):
  322. self.now = self.getnow()
  323. self.next_minute = 60 - self.now.second - 1e-6 * self.now.microsecond
  324. self.every_minute = self.crontab()
  325. self.quarterly = self.crontab(minute='*/15')
  326. self.hourly = self.crontab(minute=30)
  327. self.daily = self.crontab(hour=7, minute=30)
  328. self.weekly = self.crontab(hour=7, minute=30, day_of_week='thursday')
  329. self.monthly = self.crontab(
  330. hour=7, minute=30, day_of_week='thursday', day_of_month='8-14',
  331. )
  332. self.monthly_moy = self.crontab(
  333. hour=22, day_of_week='*', month_of_year='2',
  334. day_of_month='26,27,28',
  335. )
  336. self.yearly = self.crontab(
  337. hour=7, minute=30, day_of_week='thursday',
  338. day_of_month='8-14', month_of_year=3,
  339. )
  340. def crontab(self, *args, **kwargs):
  341. return crontab(*args, **dict(kwargs, app=self.app))
  342. def test_default_crontab_spec(self):
  343. c = self.crontab()
  344. self.assertEqual(c.minute, set(range(60)))
  345. self.assertEqual(c.hour, set(range(24)))
  346. self.assertEqual(c.day_of_week, set(range(7)))
  347. self.assertEqual(c.day_of_month, set(range(1, 32)))
  348. self.assertEqual(c.month_of_year, set(range(1, 13)))
  349. def test_simple_crontab_spec(self):
  350. c = self.crontab(minute=30)
  351. self.assertEqual(c.minute, set([30]))
  352. self.assertEqual(c.hour, set(range(24)))
  353. self.assertEqual(c.day_of_week, set(range(7)))
  354. self.assertEqual(c.day_of_month, set(range(1, 32)))
  355. self.assertEqual(c.month_of_year, set(range(1, 13)))
  356. def test_crontab_spec_minute_formats(self):
  357. c = self.crontab(minute=30)
  358. self.assertEqual(c.minute, set([30]))
  359. c = self.crontab(minute='30')
  360. self.assertEqual(c.minute, set([30]))
  361. c = self.crontab(minute=(30, 40, 50))
  362. self.assertEqual(c.minute, set([30, 40, 50]))
  363. c = self.crontab(minute=set([30, 40, 50]))
  364. self.assertEqual(c.minute, set([30, 40, 50]))
  365. def test_crontab_spec_invalid_minute(self):
  366. with self.assertRaises(ValueError):
  367. self.crontab(minute=60)
  368. with self.assertRaises(ValueError):
  369. self.crontab(minute='0-100')
  370. def test_crontab_spec_hour_formats(self):
  371. c = self.crontab(hour=6)
  372. self.assertEqual(c.hour, set([6]))
  373. c = self.crontab(hour='5')
  374. self.assertEqual(c.hour, set([5]))
  375. c = self.crontab(hour=(4, 8, 12))
  376. self.assertEqual(c.hour, set([4, 8, 12]))
  377. def test_crontab_spec_invalid_hour(self):
  378. with self.assertRaises(ValueError):
  379. self.crontab(hour=24)
  380. with self.assertRaises(ValueError):
  381. self.crontab(hour='0-30')
  382. def test_crontab_spec_dow_formats(self):
  383. c = self.crontab(day_of_week=5)
  384. self.assertEqual(c.day_of_week, set([5]))
  385. c = self.crontab(day_of_week='5')
  386. self.assertEqual(c.day_of_week, set([5]))
  387. c = self.crontab(day_of_week='fri')
  388. self.assertEqual(c.day_of_week, set([5]))
  389. c = self.crontab(day_of_week='tuesday,sunday,fri')
  390. self.assertEqual(c.day_of_week, set([0, 2, 5]))
  391. c = self.crontab(day_of_week='mon-fri')
  392. self.assertEqual(c.day_of_week, set([1, 2, 3, 4, 5]))
  393. c = self.crontab(day_of_week='*/2')
  394. self.assertEqual(c.day_of_week, set([0, 2, 4, 6]))
  395. def test_crontab_spec_invalid_dow(self):
  396. with self.assertRaises(ValueError):
  397. self.crontab(day_of_week='fooday-barday')
  398. with self.assertRaises(ValueError):
  399. self.crontab(day_of_week='1,4,foo')
  400. with self.assertRaises(ValueError):
  401. self.crontab(day_of_week='7')
  402. with self.assertRaises(ValueError):
  403. self.crontab(day_of_week='12')
  404. def test_crontab_spec_dom_formats(self):
  405. c = self.crontab(day_of_month=5)
  406. self.assertEqual(c.day_of_month, set([5]))
  407. c = self.crontab(day_of_month='5')
  408. self.assertEqual(c.day_of_month, set([5]))
  409. c = self.crontab(day_of_month='2,4,6')
  410. self.assertEqual(c.day_of_month, set([2, 4, 6]))
  411. c = self.crontab(day_of_month='*/5')
  412. self.assertEqual(c.day_of_month, set([1, 6, 11, 16, 21, 26, 31]))
  413. def test_crontab_spec_invalid_dom(self):
  414. with self.assertRaises(ValueError):
  415. self.crontab(day_of_month=0)
  416. with self.assertRaises(ValueError):
  417. self.crontab(day_of_month='0-10')
  418. with self.assertRaises(ValueError):
  419. self.crontab(day_of_month=32)
  420. with self.assertRaises(ValueError):
  421. self.crontab(day_of_month='31,32')
  422. def test_crontab_spec_moy_formats(self):
  423. c = self.crontab(month_of_year=1)
  424. self.assertEqual(c.month_of_year, set([1]))
  425. c = self.crontab(month_of_year='1')
  426. self.assertEqual(c.month_of_year, set([1]))
  427. c = self.crontab(month_of_year='2,4,6')
  428. self.assertEqual(c.month_of_year, set([2, 4, 6]))
  429. c = self.crontab(month_of_year='*/2')
  430. self.assertEqual(c.month_of_year, set([1, 3, 5, 7, 9, 11]))
  431. c = self.crontab(month_of_year='2-12/2')
  432. self.assertEqual(c.month_of_year, set([2, 4, 6, 8, 10, 12]))
  433. def test_crontab_spec_invalid_moy(self):
  434. with self.assertRaises(ValueError):
  435. self.crontab(month_of_year=0)
  436. with self.assertRaises(ValueError):
  437. self.crontab(month_of_year='0-5')
  438. with self.assertRaises(ValueError):
  439. self.crontab(month_of_year=13)
  440. with self.assertRaises(ValueError):
  441. self.crontab(month_of_year='12,13')
  442. def seconds_almost_equal(self, a, b, precision):
  443. for index, skew in enumerate((+0.1, 0, -0.1)):
  444. try:
  445. self.assertAlmostEqual(a, b + skew, precision)
  446. except AssertionError:
  447. if index + 1 >= 3:
  448. raise
  449. else:
  450. break
  451. def assertRelativedelta(self, due, last_ran):
  452. try:
  453. from dateutil.relativedelta import relativedelta
  454. except ImportError:
  455. return
  456. l1, d1, n1 = due.remaining_delta(last_ran)
  457. l2, d2, n2 = due.remaining_delta(last_ran, ffwd=relativedelta)
  458. if not isinstance(d1, relativedelta):
  459. self.assertEqual(l1, l2)
  460. for field, value in items(d1._fields()):
  461. self.assertEqual(getattr(d1, field), value)
  462. self.assertFalse(d2.years)
  463. self.assertFalse(d2.months)
  464. self.assertFalse(d2.days)
  465. self.assertFalse(d2.leapdays)
  466. self.assertFalse(d2.hours)
  467. self.assertFalse(d2.minutes)
  468. self.assertFalse(d2.seconds)
  469. self.assertFalse(d2.microseconds)
  470. def test_every_minute_execution_is_due(self):
  471. last_ran = self.now - timedelta(seconds=61)
  472. due, remaining = self.every_minute.is_due(last_ran)
  473. self.assertRelativedelta(self.every_minute, last_ran)
  474. self.assertTrue(due)
  475. self.seconds_almost_equal(remaining, self.next_minute, 1)
  476. def test_every_minute_execution_is_not_due(self):
  477. last_ran = self.now - timedelta(seconds=self.now.second)
  478. due, remaining = self.every_minute.is_due(last_ran)
  479. self.assertFalse(due)
  480. self.seconds_almost_equal(remaining, self.next_minute, 1)
  481. def test_execution_is_due_on_saturday(self):
  482. # 29th of May 2010 is a saturday
  483. with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 29, 10, 30)):
  484. last_ran = self.now - timedelta(seconds=61)
  485. due, remaining = self.every_minute.is_due(last_ran)
  486. self.assertTrue(due)
  487. self.seconds_almost_equal(remaining, self.next_minute, 1)
  488. def test_execution_is_due_on_sunday(self):
  489. # 30th of May 2010 is a sunday
  490. with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 30, 10, 30)):
  491. last_ran = self.now - timedelta(seconds=61)
  492. due, remaining = self.every_minute.is_due(last_ran)
  493. self.assertTrue(due)
  494. self.seconds_almost_equal(remaining, self.next_minute, 1)
  495. def test_execution_is_due_on_monday(self):
  496. # 31st of May 2010 is a monday
  497. with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 31, 10, 30)):
  498. last_ran = self.now - timedelta(seconds=61)
  499. due, remaining = self.every_minute.is_due(last_ran)
  500. self.assertTrue(due)
  501. self.seconds_almost_equal(remaining, self.next_minute, 1)
  502. def test_every_hour_execution_is_due(self):
  503. with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 10, 10, 30)):
  504. due, remaining = self.hourly.is_due(datetime(2010, 5, 10, 6, 30))
  505. self.assertTrue(due)
  506. self.assertEqual(remaining, 60 * 60)
  507. def test_every_hour_execution_is_not_due(self):
  508. with patch_crontab_nowfun(self.hourly, datetime(2010, 5, 10, 10, 29)):
  509. due, remaining = self.hourly.is_due(datetime(2010, 5, 10, 9, 30))
  510. self.assertFalse(due)
  511. self.assertEqual(remaining, 60)
  512. def test_first_quarter_execution_is_due(self):
  513. with patch_crontab_nowfun(
  514. self.quarterly, datetime(2010, 5, 10, 10, 15)):
  515. due, remaining = self.quarterly.is_due(
  516. datetime(2010, 5, 10, 6, 30),
  517. )
  518. self.assertTrue(due)
  519. self.assertEqual(remaining, 15 * 60)
  520. def test_second_quarter_execution_is_due(self):
  521. with patch_crontab_nowfun(
  522. self.quarterly, datetime(2010, 5, 10, 10, 30)):
  523. due, remaining = self.quarterly.is_due(
  524. datetime(2010, 5, 10, 6, 30),
  525. )
  526. self.assertTrue(due)
  527. self.assertEqual(remaining, 15 * 60)
  528. def test_first_quarter_execution_is_not_due(self):
  529. with patch_crontab_nowfun(
  530. self.quarterly, datetime(2010, 5, 10, 10, 14)):
  531. due, remaining = self.quarterly.is_due(
  532. datetime(2010, 5, 10, 10, 0),
  533. )
  534. self.assertFalse(due)
  535. self.assertEqual(remaining, 60)
  536. def test_second_quarter_execution_is_not_due(self):
  537. with patch_crontab_nowfun(
  538. self.quarterly, datetime(2010, 5, 10, 10, 29)):
  539. due, remaining = self.quarterly.is_due(
  540. datetime(2010, 5, 10, 10, 15),
  541. )
  542. self.assertFalse(due)
  543. self.assertEqual(remaining, 60)
  544. def test_daily_execution_is_due(self):
  545. with patch_crontab_nowfun(self.daily, datetime(2010, 5, 10, 7, 30)):
  546. due, remaining = self.daily.is_due(datetime(2010, 5, 9, 7, 30))
  547. self.assertTrue(due)
  548. self.assertEqual(remaining, 24 * 60 * 60)
  549. def test_daily_execution_is_not_due(self):
  550. with patch_crontab_nowfun(self.daily, datetime(2010, 5, 10, 10, 30)):
  551. due, remaining = self.daily.is_due(datetime(2010, 5, 10, 7, 30))
  552. self.assertFalse(due)
  553. self.assertEqual(remaining, 21 * 60 * 60)
  554. def test_weekly_execution_is_due(self):
  555. with patch_crontab_nowfun(self.weekly, datetime(2010, 5, 6, 7, 30)):
  556. due, remaining = self.weekly.is_due(datetime(2010, 4, 30, 7, 30))
  557. self.assertTrue(due)
  558. self.assertEqual(remaining, 7 * 24 * 60 * 60)
  559. def test_weekly_execution_is_not_due(self):
  560. with patch_crontab_nowfun(self.weekly, datetime(2010, 5, 7, 10, 30)):
  561. due, remaining = self.weekly.is_due(datetime(2010, 5, 6, 7, 30))
  562. self.assertFalse(due)
  563. self.assertEqual(remaining, 6 * 24 * 60 * 60 - 3 * 60 * 60)
  564. def test_monthly_execution_is_due(self):
  565. with patch_crontab_nowfun(self.monthly, datetime(2010, 5, 13, 7, 30)):
  566. due, remaining = self.monthly.is_due(datetime(2010, 4, 8, 7, 30))
  567. self.assertTrue(due)
  568. self.assertEqual(remaining, 28 * 24 * 60 * 60)
  569. def test_monthly_execution_is_not_due(self):
  570. with patch_crontab_nowfun(self.monthly, datetime(2010, 5, 9, 10, 30)):
  571. due, remaining = self.monthly.is_due(datetime(2010, 4, 8, 7, 30))
  572. self.assertFalse(due)
  573. self.assertEqual(remaining, 4 * 24 * 60 * 60 - 3 * 60 * 60)
  574. def test_monthly_moy_execution_is_due(self):
  575. with patch_crontab_nowfun(
  576. self.monthly_moy, datetime(2014, 2, 26, 22, 0)):
  577. due, remaining = self.monthly_moy.is_due(
  578. datetime(2013, 7, 4, 10, 0),
  579. )
  580. self.assertTrue(due)
  581. self.assertEqual(remaining, 60.)
  582. def test_monthly_moy_execution_is_not_due(self):
  583. raise SkipTest('unstable test')
  584. with patch_crontab_nowfun(
  585. self.monthly_moy, datetime(2013, 6, 28, 14, 30)):
  586. due, remaining = self.monthly_moy.is_due(
  587. datetime(2013, 6, 28, 22, 14),
  588. )
  589. self.assertFalse(due)
  590. attempt = (
  591. time.mktime(datetime(2014, 2, 26, 22, 0).timetuple()) -
  592. time.mktime(datetime(2013, 6, 28, 14, 30).timetuple()) -
  593. 60 * 60
  594. )
  595. self.assertEqual(remaining, attempt)
  596. def test_monthly_moy_execution_is_due2(self):
  597. with patch_crontab_nowfun(
  598. self.monthly_moy, datetime(2014, 2, 26, 22, 0)):
  599. due, remaining = self.monthly_moy.is_due(
  600. datetime(2013, 2, 28, 10, 0),
  601. )
  602. self.assertTrue(due)
  603. self.assertEqual(remaining, 60.)
  604. def test_monthly_moy_execution_is_not_due2(self):
  605. with patch_crontab_nowfun(
  606. self.monthly_moy, datetime(2014, 2, 26, 21, 0)):
  607. due, remaining = self.monthly_moy.is_due(
  608. datetime(2013, 6, 28, 22, 14),
  609. )
  610. self.assertFalse(due)
  611. attempt = 60 * 60
  612. self.assertEqual(remaining, attempt)
  613. def test_yearly_execution_is_due(self):
  614. with patch_crontab_nowfun(self.yearly, datetime(2010, 3, 11, 7, 30)):
  615. due, remaining = self.yearly.is_due(datetime(2009, 3, 12, 7, 30))
  616. self.assertTrue(due)
  617. self.assertEqual(remaining, 364 * 24 * 60 * 60)
  618. def test_yearly_execution_is_not_due(self):
  619. with patch_crontab_nowfun(self.yearly, datetime(2010, 3, 7, 10, 30)):
  620. due, remaining = self.yearly.is_due(datetime(2009, 3, 12, 7, 30))
  621. self.assertFalse(due)
  622. self.assertEqual(remaining, 4 * 24 * 60 * 60 - 3 * 60 * 60)