job.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. # -*- coding: utf-8 -*-
  2. """
  3. plan.testsuite.job
  4. ~~~~~~~~~~~~~~~~~~
  5. Tests the Job classes for Plan.
  6. :copyright: (c) 2014 by Shipeng Feng.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. import sys
  10. import unittest
  11. from plan.testsuite import BaseTestCase
  12. from plan.job import is_month, is_week, get_frequency, get_moment
  13. from plan.job import Job, CommandJob, ScriptJob, ModuleJob, RawJob
  14. from plan.exceptions import ParseError, ValidationError
  15. class BasicTestCase(BaseTestCase):
  16. """Tests basic functions used by Job class."""
  17. def test_is_month(self):
  18. self.assert_true(is_month('jan'))
  19. self.assert_true(is_month('JAN'))
  20. self.assert_true(is_month('JANUARY'))
  21. self.assert_true(is_month('january'))
  22. self.assert_false(is_month('sunday'))
  23. def test_is_week(self):
  24. self.assert_true(is_week('mon'))
  25. self.assert_true(is_week('MON'))
  26. self.assert_true(is_week('monday'))
  27. self.assert_true(is_week('MONDAY'))
  28. self.assert_true(is_week('weekend'))
  29. self.assert_false(is_week('feburary'))
  30. def test_get_frequency(self):
  31. self.assert_equal(3, get_frequency('3.month'))
  32. self.assert_equal(3, get_frequency('3.'))
  33. def test_get_moment(self):
  34. self.assert_equal(3, get_moment('day.3'))
  35. self.assert_equal(3, get_moment('.3'))
  36. class JobTestCase(BaseTestCase):
  37. def test_task(self):
  38. job = CommandJob('/bin/task', every='weekend')
  39. self.assert_equal(job.cron, '0 0 * * 6,0 /bin/task')
  40. job = CommandJob('ls -l ', every='weekend')
  41. self.assert_equal(job.cron, '0 0 * * 6,0 ls -l')
  42. def test_raw_every(self):
  43. job = Job('task', every='0 1 2 3 *', at='minute.2', path='/path')
  44. self.assert_equal(job.cron, '0 1 2 3 * cd /path && task')
  45. def test_predefined_every(self):
  46. job = Job('task', every='yearly', at='minute.2', path='/path')
  47. self.assert_equal(job.cron, '@yearly cd /path && task')
  48. job = Job('task', every='monthly', at='minute.2', path='/path')
  49. self.assert_equal(job.cron, '@monthly cd /path && task')
  50. job = Job('task', every='weekly', at='minute.2', path='/path')
  51. self.assert_equal(job.cron, '@weekly cd /path && task')
  52. job = Job('task', every='daily', at='minute.2', path='/path')
  53. self.assert_equal(job.cron, '@daily cd /path && task')
  54. job = Job('task', every='hourly', at='minute.2', path='/path')
  55. self.assert_equal(job.cron, '@hourly cd /path && task')
  56. job = Job('task', every='reboot', at='minute.2', path='/path')
  57. self.assert_equal(job.cron, '@reboot cd /path && task')
  58. def test_minute_every(self):
  59. job = CommandJob('task', every='1.minute')
  60. self.assert_equal(job.cron, '* * * * * task')
  61. job = CommandJob('task', every='2.minute')
  62. self.assert_equal(job.cron, '0,2,4,6,8,10,12,14,16,18,20,22,24,26,'
  63. '28,30,32,34,36,38,40,42,44,46,48,50,52,'
  64. '54,56,58 * * * * task')
  65. job = CommandJob('task', every='10.minute')
  66. self.assert_equal(job.cron, '0,10,20,30,40,50 * * * * task')
  67. job = CommandJob('task', every='30.minute')
  68. self.assert_equal(job.cron, '0,30 * * * * task')
  69. job = CommandJob('task', every='60.minute')
  70. self.assert_equal(job.cron, '0 * * * * task')
  71. job = CommandJob('task', every='11.minute')
  72. self.assert_equal(job.cron, '11,22,33,44,55 * * * * task')
  73. def test_hour_every(self):
  74. job = CommandJob('task', every='1.hour')
  75. self.assert_equal(job.cron, '0 * * * * task')
  76. job = CommandJob('task', every='24.hour')
  77. self.assert_equal(job.cron, '0 0 * * * task')
  78. job = CommandJob('task', every='3.hour')
  79. self.assert_equal(job.cron, '0 0,3,6,9,12,15,18,21 * * * task')
  80. job = CommandJob('task', every='5.hour')
  81. self.assert_equal(job.cron, '0 5,10,15,20 * * * task')
  82. def test_day_every(self):
  83. job = CommandJob('task', every='1.day')
  84. self.assert_equal(job.cron, '0 0 * * * task')
  85. job = CommandJob('task', every='3.day')
  86. self.assert_equal(job.cron, '0 0 4,7,10,13,16,19,22,25,28,31 * * task')
  87. job = CommandJob('task', every='31.day')
  88. self.assert_equal(job.cron, '0 0 1 * * task')
  89. def test_month_every(self):
  90. job = CommandJob('task', every='1.month')
  91. self.assert_equal(job.cron, '0 0 1 * * task')
  92. job = CommandJob('task', every='2.month')
  93. self.assert_equal(job.cron, '0 0 1 1,3,5,7,9,11 * task')
  94. job = CommandJob('task', every='5.month')
  95. self.assert_equal(job.cron, '0 0 1 6,11 * task')
  96. job = CommandJob('task', every='january')
  97. self.assert_equal(job.cron, '0 0 1 1 * task')
  98. def test_week_every(self):
  99. job = CommandJob('task', every='monday')
  100. self.assert_equal(job.cron, '0 0 * * 1 task')
  101. job = CommandJob('task', every='sunday')
  102. self.assert_equal(job.cron, '0 0 * * 0 task')
  103. job = CommandJob('task', every='saturday')
  104. self.assert_equal(job.cron, '0 0 * * 6 task')
  105. job = CommandJob('task', every='weekday')
  106. self.assert_equal(job.cron, '0 0 * * 1,2,3,4,5 task')
  107. job = CommandJob('task', every='weekend')
  108. self.assert_equal(job.cron, '0 0 * * 6,0 task')
  109. def test_every_parse_error(self):
  110. job = CommandJob('task', every='1.century')
  111. self.assert_raises(ParseError, lambda: job.cron)
  112. job = CommandJob('task', every='0.minute')
  113. self.assert_raises(ParseError, lambda: job.cron)
  114. job = CommandJob('task', every='61.minute')
  115. self.assert_raises(ParseError, lambda: job.cron)
  116. job = CommandJob('task', every='0.hour')
  117. self.assert_raises(ParseError, lambda: job.cron)
  118. job = CommandJob('task', every='25.hour')
  119. self.assert_raises(ParseError, lambda: job.cron)
  120. job = CommandJob('task', every='0.day')
  121. self.assert_raises(ParseError, lambda: job.cron)
  122. job = CommandJob('task', every='32.day')
  123. self.assert_raises(ParseError, lambda: job.cron)
  124. job = CommandJob('task', every='0.month')
  125. self.assert_raises(ParseError, lambda: job.cron)
  126. job = CommandJob('task', every='13.month')
  127. self.assert_raises(ParseError, lambda: job.cron)
  128. job = CommandJob('task', every='0.year')
  129. self.assert_raises(ParseError, lambda: job.cron)
  130. job = CommandJob('task', every='2.year')
  131. self.assert_raises(ParseError, lambda: job.cron)
  132. def test_preprocess_at(self):
  133. job = Job('job', every='1.hour')
  134. at = job.preprocess_at('0:0')
  135. self.assert_equal(at, 'hour.0 minute.0')
  136. at = job.preprocess_at('1:00')
  137. self.assert_equal(at, 'hour.1 minute.0')
  138. at = job.preprocess_at('23:01')
  139. self.assert_equal(at, 'hour.23 minute.1')
  140. at = job.preprocess_at('23:10')
  141. self.assert_equal(at, 'hour.23 minute.10')
  142. at = job.preprocess_at('12:59')
  143. self.assert_equal(at, 'hour.12 minute.59')
  144. at = job.preprocess_at('14:09:0')
  145. self.assert_equal(at, 'hour.14 minute.9')
  146. def test_minute_at(self):
  147. job = CommandJob('task', every='1.hour', at='minute.5')
  148. self.assert_equal(job.cron, '5 * * * * task')
  149. job = CommandJob('task', every='1.day', at='minute.1')
  150. self.assert_equal(job.cron, '1 0 * * * task')
  151. job = CommandJob('task', every='1.month', at='minute.59')
  152. self.assert_equal(job.cron, '59 0 1 * * task')
  153. job = CommandJob('task', every='monday', at='minute.30')
  154. self.assert_equal(job.cron, '30 0 * * 1 task')
  155. def test_hour_at(self):
  156. job = CommandJob('task', every='1.day', at='hour.1')
  157. self.assert_equal(job.cron, '0 1 * * * task')
  158. job = CommandJob('task', every='1.month', at='hour.0')
  159. self.assert_equal(job.cron, '0 0 1 * * task')
  160. job = CommandJob('task', every='monday', at='hour.23')
  161. self.assert_equal(job.cron, '0 23 * * 1 task')
  162. def test_day_at(self):
  163. job = CommandJob('task', every='1.month', at='day.5')
  164. self.assert_equal(job.cron, '0 0 5 * * task')
  165. def test_week_at(self):
  166. job = CommandJob('task', every='1.month', at='sunday')
  167. self.assert_equal(job.cron, '0 0 1 * 0 task')
  168. def test_at(self):
  169. job = CommandJob('task', every='1.month', at='day.1 hour.1 minute.0')
  170. self.assert_equal(job.cron, '0 1 1 * * task')
  171. job = CommandJob('task', every='1.month', at='day.1 12:00')
  172. self.assert_equal(job.cron, '0 12 1 * * task')
  173. job = CommandJob('task', every='1.month',
  174. at='day.1 hour.1 minute.5 minute.10')
  175. self.assert_equal(job.cron, '5,10 1 1 * * task')
  176. job = CommandJob('task', every='1.month',
  177. at='day.15 10:55 10:56')
  178. self.assert_equal(job.cron, '55,56 10 15 * * task')
  179. def test_at_parse_error(self):
  180. job = CommandJob('task', every='jan', at='minute.60')
  181. self.assert_raises(ParseError, lambda: job.cron)
  182. job = CommandJob('task', every='jan', at='hour.24')
  183. self.assert_raises(ParseError, lambda: job.cron)
  184. job = CommandJob('task', every='jan', at='day.0')
  185. self.assert_raises(ParseError, lambda: job.cron)
  186. job = CommandJob('task', every='jan', at='day.32')
  187. self.assert_raises(ParseError, lambda: job.cron)
  188. job = CommandJob('task', every='jan', at='month.12')
  189. self.assert_raises(ParseError, lambda: job.cron)
  190. job = CommandJob('task', every='jan', at='year.1')
  191. self.assert_raises(ParseError, lambda: job.cron)
  192. job = CommandJob('task', every='jan', at='whenever')
  193. self.assert_raises(ParseError, lambda: job.cron)
  194. def test_every_at_validation_error(self):
  195. job = CommandJob('task', every='1.minute', at='minute.1')
  196. self.assert_raises(ValidationError, lambda: job.cron)
  197. job = CommandJob('task', every='1.minute', at='hour.23')
  198. self.assert_raises(ValidationError, lambda: job.cron)
  199. job = CommandJob('task', every='1.minute', at='day.1')
  200. self.assert_raises(ValidationError, lambda: job.cron)
  201. job = CommandJob('task', every='1.minute', at='sunday')
  202. self.assert_raises(ValidationError, lambda: job.cron)
  203. job = CommandJob('task', every='1.hour', at='hour.23')
  204. self.assert_raises(ValidationError, lambda: job.cron)
  205. job = CommandJob('task', every='1.hour', at='day.1')
  206. self.assert_raises(ValidationError, lambda: job.cron)
  207. job = CommandJob('task', every='1.hour', at='sunday')
  208. self.assert_raises(ValidationError, lambda: job.cron)
  209. job = CommandJob('task', every='1.day', at='day.1')
  210. self.assert_raises(ValidationError, lambda: job.cron)
  211. job = CommandJob('task', every='1.day', at='sunday')
  212. self.assert_raises(ValidationError, lambda: job.cron)
  213. job = CommandJob('task', every='sunday', at='day.1')
  214. self.assert_raises(ValidationError, lambda: job.cron)
  215. job = CommandJob('task', every='sunday', at='sunday')
  216. self.assert_raises(ValidationError, lambda: job.cron)
  217. def test_path(self):
  218. job = ScriptJob('script.py', every='1.day', path='/web/scripts')
  219. self.assert_equal(job.cron, '0 0 * * * cd /web/scripts && %s script.py'
  220. % sys.executable)
  221. def test_environment(self):
  222. job = ScriptJob('script.py', every='1.day', path='/web/scripts',
  223. environment={'k': 'v'})
  224. self.assert_equal(job.cron, '0 0 * * * cd /web/scripts && k=v %s'
  225. ' script.py' % sys.executable)
  226. def test_output(self):
  227. job = ScriptJob('script.py', every='1.day', path='/web/scripts',
  228. output=dict(stdout='/log/out.log',
  229. stderr='/log/err.log'))
  230. self.assert_equal(job.cron, '0 0 * * * cd /web/scripts && %s script.py'
  231. ' >> /log/out.log 2>> /log/err.log' % sys.executable)
  232. def test_job(self):
  233. job = Job('job', every='1.day', path='/tmp',
  234. environment={'key': 'value'}, output='null')
  235. self.assert_equal(job.cron, '0 0 * * * cd /tmp && key=value job '
  236. '> /dev/null 2>&1')
  237. def test_command_job(self):
  238. job = CommandJob('command', every='1.day', output='null')
  239. self.assert_equal(job.cron, '0 0 * * * command > /dev/null 2>&1')
  240. def test_script_job(self):
  241. job = ScriptJob('script.py', every='1.day', path='/tmp',
  242. environment={'key': 'value'}, output='null')
  243. self.assert_equal(job.cron, '0 0 * * * cd /tmp && key=value %s'
  244. ' script.py > /dev/null 2>&1' % sys.executable)
  245. def test_module_job(self):
  246. job = ModuleJob('calendar', every='1.day',
  247. environment={'key': 'value'}, output='null')
  248. self.assert_equal(job.cron, '0 0 * * * key=value %s -m calendar'
  249. ' > /dev/null 2>&1' % sys.executable)
  250. def test_raw_job(self):
  251. job = RawJob('raw ???? my job', every='1.day')
  252. self.assert_equal(job.cron, '0 0 * * * raw ???? my job')
  253. def suite():
  254. suite = unittest.TestSuite()
  255. suite.addTest(unittest.makeSuite(BasicTestCase))
  256. suite.addTest(unittest.makeSuite(JobTestCase))
  257. return suite