PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/xivo_agid/tests/test_schedule.py

https://gitlab.com/xivo.solutions/xivo-agid
Python | 335 lines | 228 code | 91 blank | 16 comment | 1 complexity | bef28726e609d198f22ffb491efbcc55 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. # Copyright (C) 2013-2014 Avencall
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>
  16. import datetime
  17. import unittest
  18. from mock import Mock, call
  19. from xivo_agid.schedule import ScheduleBuilder, SchedulePeriodBuilder, \
  20. HoursChecker, WeekdaysChecker, DaysChecker, MonthsChecker, SchedulePeriod, \
  21. ScheduleAction
  22. class TestHoursChecker(unittest.TestCase):
  23. def test_range_is_in(self):
  24. value = '08:05-08:10'
  25. current_time = _a_time().hour('08:07').build()
  26. self._assert_time_is_in(current_time, value)
  27. def _assert_time_is_in(self, current_time, value):
  28. hours_checker = HoursChecker.new_from_value(value)
  29. self.assertTrue(hours_checker.is_in(current_time))
  30. def _assert_time_is_not_in(self, current_time, value):
  31. hours_checker = HoursChecker.new_from_value(value)
  32. self.assertFalse(hours_checker.is_in(current_time))
  33. def test_upper_limit_is_not_in(self):
  34. value = '08:05-08:10'
  35. current_time = _a_time().hour('08:10').build()
  36. self._assert_time_is_not_in(current_time, value)
  37. def test_lower_limit_is_in(self):
  38. value = '08:05-08:10'
  39. current_time = _a_time().hour('08:05').build()
  40. self._assert_time_is_in(current_time, value)
  41. def test_upper_limit_plus_one_is_not_in(self):
  42. value = '08:05-08:10'
  43. current_time = _a_time().hour('08:11').build()
  44. self._assert_time_is_not_in(current_time, value)
  45. def test_upper_limit_less_one_is_not_in(self):
  46. value = '08:05-08:10'
  47. current_time = _a_time().hour('08:04').build()
  48. self._assert_time_is_not_in(current_time, value)
  49. def test_minute_is_in_but_hour_is_more(self):
  50. value = '08:05-08:10'
  51. current_time = _a_time().hour('09:07').build()
  52. self._assert_time_is_not_in(current_time, value)
  53. def test_minute_is_in_but_hour_is_less(self):
  54. value = '08:05-08:10'
  55. current_time = _a_time().hour('07:07').build()
  56. self._assert_time_is_not_in(current_time, value)
  57. class TestWeekdaysChecker(unittest.TestCase):
  58. def test_single_weekday_is_in(self):
  59. value = '3'
  60. current_time = _a_time().weekday('3').build()
  61. self._assert_time_is_in(current_time, value)
  62. def _assert_time_is_in(self, current_time, value):
  63. weekdays_checker = WeekdaysChecker.new_from_value(value)
  64. self.assertTrue(weekdays_checker.is_in(current_time))
  65. def _assert_time_is_not_in(self, current_time, value):
  66. weekdays_checker = WeekdaysChecker.new_from_value(value)
  67. self.assertFalse(weekdays_checker.is_in(current_time))
  68. def test_single_weekday_range_is_in(self):
  69. value = '1-5'
  70. current_time = _a_time().weekday('3').build()
  71. self._assert_time_is_in(current_time, value)
  72. def test_upper_limit_single_weekday_range(self):
  73. value = '1-5'
  74. current_time = _a_time().weekday('5').build()
  75. self._assert_time_is_in(current_time, value)
  76. def test_lower_limit_single_weekday_range(self):
  77. value = '1-5'
  78. current_time = _a_time().weekday('1').build()
  79. self._assert_time_is_in(current_time, value)
  80. def test_upper_limit_plus_one_is_not_in(self):
  81. value = '1-5'
  82. current_time = _a_time().weekday('6').build()
  83. self._assert_time_is_not_in(current_time, value)
  84. def test_lower_limit_less_one_is_not_in(self):
  85. value = '2-5'
  86. current_time = _a_time().weekday('1').build()
  87. self._assert_time_is_not_in(current_time, value)
  88. def test_mixed_weekday_range_is_in(self):
  89. value = '1,3-4,7'
  90. weekdays_checker = WeekdaysChecker.new_from_value(value)
  91. self.assertTrue(weekdays_checker.is_in(_a_time().weekday('1').build()))
  92. self.assertFalse(weekdays_checker.is_in(_a_time().weekday('2').build()))
  93. self.assertTrue(weekdays_checker.is_in(_a_time().weekday('3').build()))
  94. self.assertTrue(weekdays_checker.is_in(_a_time().weekday('4').build()))
  95. self.assertFalse(weekdays_checker.is_in(_a_time().weekday('5').build()))
  96. self.assertFalse(weekdays_checker.is_in(_a_time().weekday('6').build()))
  97. self.assertTrue(weekdays_checker.is_in(_a_time().weekday('7').build()))
  98. class TestDaysChecker(unittest.TestCase):
  99. def test_simple_day(self):
  100. value = '5'
  101. days_checker = DaysChecker.new_from_value(value)
  102. self.assertTrue(days_checker.is_in(_a_time().day('5').build()))
  103. self.assertFalse(days_checker.is_in(_a_time().day('6').build()))
  104. class TestMonthsChecker(unittest.TestCase):
  105. def test_simple_month(self):
  106. value = '5'
  107. months_checker = MonthsChecker.new_from_value(value)
  108. self.assertTrue(months_checker.is_in(_a_time().month('5').build()))
  109. self.assertFalse(months_checker.is_in(_a_time().month('6').build()))
  110. class TestSchedulePeriod(unittest.TestCase):
  111. def test_is_in_with_true_checker(self):
  112. checker = self._new_true_checker()
  113. schedule_period = SchedulePeriod([checker], None)
  114. self.assertTrue(schedule_period.is_in(None))
  115. def _new_true_checker(self):
  116. mock = Mock()
  117. mock.is_in.return_value = True
  118. return mock
  119. def test_is_in_with_false_checker(self):
  120. checker = self._new_false_checker()
  121. schedule_period = SchedulePeriod([checker], None)
  122. self.assertFalse(schedule_period.is_in(None))
  123. def _new_false_checker(self):
  124. mock = Mock()
  125. mock.is_in.return_value = False
  126. return mock
  127. def test_is_in_with_true_and_false_checker(self):
  128. checker1 = self._new_true_checker()
  129. checker2 = self._new_false_checker()
  130. schedule_period = SchedulePeriod([checker1, checker2], None)
  131. self.assertFalse(schedule_period.is_in(None))
  132. class TestSchedule(unittest.TestCase):
  133. def test_schedule_is_opened_when_hours_is_in_open_period(self):
  134. schedule = (_a_schedule()
  135. .opened(_a_period()
  136. .hours('18:00-18:10').build())
  137. .build())
  138. current_time = (_a_time()
  139. .hour('18:05')
  140. .build())
  141. self._assert_schedule_is_in_state(schedule, current_time, 'opened')
  142. def _assert_schedule_is_in_state(self, schedule, current_time, state, action=None):
  143. schedule_state = schedule.compute_state(current_time)
  144. self.assertEqual(state, schedule_state.state)
  145. if action is not None:
  146. self.assertEqual(action, schedule_state.action)
  147. def test_simple_schedule_is_closed_when_hours_not_in_open_period(self):
  148. schedule = (_a_schedule()
  149. .opened(_a_period()
  150. .hours('18:00-18:10').build())
  151. .build())
  152. current_time = (_a_time()
  153. .hour('18:15')
  154. .build())
  155. self._assert_schedule_is_in_state(schedule, current_time, 'closed')
  156. def test_schedule_is_closed_when_day_doesnt_match(self):
  157. schedule = (_a_schedule()
  158. .opened(_a_period()
  159. .days('22').build())
  160. .build())
  161. current_time = (_a_time()
  162. .day('23')
  163. .build())
  164. self._assert_schedule_is_in_state(schedule, current_time, 'closed')
  165. def test_schedule_is_closed_when_weekday_doesnt_match(self):
  166. schedule = (_a_schedule()
  167. .opened(_a_period()
  168. .weekdays('6').build())
  169. .build())
  170. current_time = (_a_time()
  171. .weekday('7')
  172. .build())
  173. self._assert_schedule_is_in_state(schedule, current_time, 'closed')
  174. def test_schedule_is_closed_when_month_doesnt_match(self):
  175. schedule = (_a_schedule()
  176. .opened(_a_period()
  177. .months('3').build())
  178. .build())
  179. current_time = (_a_time()
  180. .month('4')
  181. .build())
  182. self._assert_schedule_is_in_state(schedule, current_time, 'closed')
  183. def test_complex_schedule(self):
  184. schedule = (_a_schedule()
  185. .opened(_a_period()
  186. .hours('16:00-17:00').build())
  187. .closed(_a_period()
  188. .hours('16:05-16:07')
  189. .days('5')
  190. .action(1).build())
  191. .closed(_a_period()
  192. .hours('16:05-16:07')
  193. .days('6')
  194. .action(2).build())
  195. .build())
  196. current_time_builder = (_a_time()
  197. .hour('16:06'))
  198. current_time = current_time_builder.day('5').build()
  199. self._assert_schedule_is_in_state(schedule, current_time, 'closed', action=1)
  200. current_time = current_time_builder.day('6').build()
  201. self._assert_schedule_is_in_state(schedule, current_time, 'closed', action=2)
  202. current_time = current_time_builder.day('7').build()
  203. self._assert_schedule_is_in_state(schedule, current_time, 'opened')
  204. def _a_schedule():
  205. return ScheduleBuilder()
  206. def _a_period():
  207. return SchedulePeriodBuilder()
  208. def _a_time():
  209. return _DatetimeBuilder()
  210. class _DatetimeBuilder(object):
  211. def __init__(self):
  212. self._year = 1970
  213. self._month = 1
  214. self._day = 1
  215. self._hour = 0
  216. self._minute = 0
  217. def hour(self, hour):
  218. hour, minute = hour.split(':', 1)
  219. self._hour = int(hour)
  220. self._minute = int(minute)
  221. return self
  222. def month(self, month):
  223. self._month = int(month)
  224. return self
  225. def day(self, day):
  226. self._day = int(day)
  227. return self
  228. def weekday(self, weekday):
  229. # monday = 1, sunday = 7
  230. weekday = int(weekday)
  231. self._year = 1970
  232. self._month = 1
  233. self._day = 4 + weekday
  234. return self
  235. def build(self):
  236. return datetime.datetime(self._year, self._month, self._day, self._hour, self._minute)
  237. class TestScheduleAction(unittest.TestCase):
  238. def test_action_arg2_is_not_set_if_none(self):
  239. action = ScheduleAction('foo', 'bar', None)
  240. agi = Mock()
  241. action.set_variables_in_agi(agi)
  242. expected_call_args = [call('XIVO_FWD_SCHEDULE_OUT_ACTION', 'foo'),
  243. call('XIVO_FWD_SCHEDULE_OUT_ACTIONARG1', 'bar')]
  244. self.assertEqual(expected_call_args, agi.set_variable.call_args_list)