/sendinel/backend/tests/scheduler_test.py

https://github.com/AdeneganJosiah/Sendinel · Python · 314 lines · 196 code · 89 blank · 29 comment · 2 complexity · f5d35ffdb13f8059fea47b9d1528e95a MD5 · raw file

  1. from django.test import TestCase
  2. from datetime import datetime, timedelta
  3. from sendinel.backend.models import ScheduledEvent, \
  4. Patient, \
  5. WayOfCommunication, \
  6. get_woc
  7. from sendinel.infoservices.models import InfoMessage
  8. from sendinel.backend import output, scheduler
  9. from sendinel import settings
  10. class SchedulerTest(TestCase):
  11. counter = 0
  12. fixtures = ['backend_test']
  13. def test_scheduler(self):
  14. def scheduled_events_count(state = 'new'):
  15. return scheduler.get_all_due_events().count()
  16. def queued_events_count(state = 'queued'):
  17. return scheduler.get_all_queued_events().count()
  18. def send(data):
  19. SchedulerTest.counter += 1
  20. def mock_process_events():
  21. for event in scheduler.get_all_queued_events():
  22. event.state = "done"
  23. event.save()
  24. sms_send_old = output.SMSOutputData.send
  25. bluetooth_send_old = output.BluetoothOutputData.send
  26. voice_send_old = output.VoiceOutputData.send
  27. output.SMSOutputData.send = send
  28. output.BluetoothOutputData.send = send
  29. output.VoiceOutputData.send = send
  30. SchedulerTest.counter = 0
  31. self.assertTrue(scheduled_events_count() > 0)
  32. scheduler.run(run_only_one_time = True)
  33. # assert that all scheduled events have been processed by send()
  34. # as defined in fixtures there is one usergroup with 2 members and
  35. # one single patient
  36. # exactly two messages were scheduled and had the state "new"
  37. # we expect only one message to be processed at a time, so
  38. # the second one has to stay with state "new"
  39. self.assertEquals(1, SchedulerTest.counter)
  40. # assert that one event has been processed and one is left
  41. self.assertEquals(scheduled_events_count(), 1)
  42. self.assertEquals(queued_events_count(), 1)
  43. # running the scheduler again should not change the situation,
  44. # because the fact that the file is still in queue means that
  45. # has not been processed yet
  46. scheduler.run(run_only_one_time = True)
  47. self.assertEquals(1, SchedulerTest.counter)
  48. self.assertEquals(scheduled_events_count(), 1)
  49. self.assertEquals(queued_events_count(), 1)
  50. # let's pretend the Asterisk server has processed the file
  51. mock_process_events()
  52. self.assertEquals(queued_events_count(), 0)
  53. # now the scheduler is run again and should process the one event left
  54. scheduler.run(run_only_one_time = True)
  55. # assert that no events with state new exist anymore and one is queued
  56. self.assertEquals(scheduled_events_count(), 0)
  57. self.assertEquals(queued_events_count(), 1)
  58. # Now we also process the last event and ensure there's none left
  59. mock_process_events()
  60. self.assertEquals(queued_events_count(), 0)
  61. # Running the scheduler without any due event should be no problem
  62. scheduler.run(run_only_one_time = True)
  63. output.SMSOutputData.send = sms_send_old
  64. output.BluetoothOutputData.send = bluetooth_send_old
  65. output.VoiceOutputData.send = voice_send_old
  66. def test_spool_file_parsing(self):
  67. class MockFile:
  68. """
  69. This class represents a mocked file object
  70. It defaults to an untouched Asterisk spool file
  71. """
  72. counter = 0
  73. fake_data = """Channel: Local/2000
  74. WaitTime: 2
  75. RetryTime: 5
  76. MaxRetries: 8000
  77. Data: datacard0,0123456,This is a Test
  78. Archive: true
  79. """
  80. def readline(input):
  81. try:
  82. data = MockFile.fake_data.splitlines()[MockFile.counter]
  83. except:
  84. return None
  85. MockFile.counter += 1
  86. return data
  87. real_open = scheduler.openFile
  88. fake_open = lambda filename: MockFile()
  89. scheduler.openFile = fake_open
  90. filename = "testspoolfile"
  91. status = scheduler.get_spoolfile_status(filename)
  92. self.assertEquals(status, "Queued")
  93. MockFile.counter = 0
  94. # pay attention to the space in the empty line, because in a real
  95. # file an empty line behaves more like a line with a space in it
  96. MockFile.fake_data = """Channel: Local/2000
  97. WaitTime: 2
  98. RetryTime: 5
  99. MaxRetries: 8000
  100. Data: datacard0,0123456,This is a Test
  101. Archive: true
  102. Status: Failed
  103. """
  104. status = scheduler.get_spoolfile_status(filename)
  105. self.assertEquals(status, "Failed")
  106. scheduler.openFile = real_open
  107. MockFile.counter = 0
  108. def test_check_spool_files(self):
  109. def get_mock_status(filename):
  110. """
  111. This is a mock method to represent check_spoolfile_status
  112. It is told which status to return by using the (in this case
  113. useless) filename parameter
  114. """
  115. return filename
  116. original_get_spoolfile_status = scheduler.get_spoolfile_status
  117. scheduler.get_spoolfile_status = get_mock_status
  118. patient = Patient()
  119. patient.save()
  120. sendable = InfoMessage(text="Test Message",
  121. way_of_communication = get_woc("sms"))
  122. sendable.recipient = patient
  123. sendable.save()
  124. event1 = ScheduledEvent(sendable=sendable,
  125. send_time=datetime.now(),
  126. state = "queued",
  127. filename = "Completed")
  128. event1.save()
  129. event2 = ScheduledEvent(sendable=sendable,
  130. send_time=datetime.now(),
  131. state = "queued",
  132. filename = "Expired")
  133. event2.save()
  134. # now: the real testing
  135. scheduler.check_spool_files()
  136. self.assertEquals(ScheduledEvent.objects.get(pk = event1.pk).state, \
  137. "done")
  138. self.assertEquals(ScheduledEvent.objects.get(pk = event2.pk).state, \
  139. "new")
  140. event2.filename = "Expired"
  141. event2.save()
  142. scheduler.check_spool_files()
  143. self.assertEquals(ScheduledEvent.objects.get(pk = event2.pk).state, \
  144. "new")
  145. self.assertEquals(ScheduledEvent.objects.get(pk = event2.pk).retry, 1)
  146. event2.retry = settings.ASTERISK_RETRY
  147. event2.filename = "Expired"
  148. event2.save()
  149. scheduler.check_spool_files()
  150. self.assertEquals(ScheduledEvent.objects.get(pk = event2.pk).state, \
  151. "failed")
  152. event3 = ScheduledEvent(sendable=sendable,
  153. send_time=datetime.now(),
  154. state = "queued",
  155. filename = "Failed")
  156. event3.save()
  157. scheduler.check_spool_files()
  158. self.assertEquals(ScheduledEvent.objects.get(pk = event3.pk).state, \
  159. "failed")
  160. # change everything back to normal
  161. event1.delete()
  162. event2.delete()
  163. event3.delete()
  164. scheduler.get_spoolfile_status = original_get_spoolfile_status
  165. def test_get_all_queued_events(self):
  166. patient = Patient()
  167. patient.save()
  168. sendable = InfoMessage(text="Test Message",
  169. way_of_communication = get_woc("sms"))
  170. sendable.recipient = patient
  171. sendable.save()
  172. self.assertEquals(scheduler.get_all_queued_events().count(), 0)
  173. schedule1 = ScheduledEvent(sendable=sendable,
  174. send_time=datetime.now(),
  175. state = "queued")
  176. schedule1.save()
  177. self.assertEquals(scheduler.get_all_queued_events().count(), 1)
  178. schedule2 = ScheduledEvent(sendable=sendable,
  179. send_time=(datetime.now() - timedelta(days=1)),
  180. state = "sent")
  181. schedule2.save()
  182. self.assertTrue(schedule1 in scheduler.get_all_queued_events())
  183. self.assertFalse(schedule2 in scheduler.get_all_queued_events())
  184. self.assertEquals(scheduler.get_all_queued_events().count(), 1)
  185. schedule2.state = "queued"
  186. schedule2.save()
  187. self.assertEquals(scheduler.get_all_queued_events().count(), 2)
  188. schedule1.delete()
  189. schedule2.delete()
  190. def test_get_all_due_events(self):
  191. patient = Patient()
  192. patient.save()
  193. # The fixtures already contain two due events
  194. self.assertEquals(scheduler.get_all_due_events().count(), 2)
  195. sendable = InfoMessage(text="Test Message",
  196. way_of_communication = get_woc("sms"))
  197. sendable.recipient = patient
  198. sendable.save()
  199. schedule1 = ScheduledEvent(sendable=sendable, send_time=datetime.now())
  200. schedule1.save()
  201. schedule2 = ScheduledEvent(sendable=sendable,
  202. send_time=(datetime.now() - timedelta(days=1)))
  203. schedule2.save()
  204. schedule3 = ScheduledEvent(sendable=sendable,
  205. send_time=(datetime.now() + timedelta(days=1)))
  206. schedule3.save()
  207. self.assertEquals(scheduler.get_all_due_events().count(), 4)
  208. self.assertTrue(schedule1 in scheduler.get_all_due_events())
  209. self.assertTrue(schedule2 in scheduler.get_all_due_events())
  210. self.assertFalse(schedule3 in scheduler.get_all_due_events())
  211. schedule4 = ScheduledEvent(sendable=sendable,
  212. send_time=datetime.now(),
  213. state = "failed")
  214. schedule4.save()
  215. schedule5 = ScheduledEvent(sendable=sendable,
  216. send_time=(datetime.now() - timedelta(days=1)),
  217. state = "sent")
  218. schedule5.save()
  219. self.assertEquals(scheduler.get_all_due_events().count(), 4)
  220. schedule1.delete()
  221. schedule2.delete()
  222. schedule3.delete()
  223. schedule4.delete()
  224. schedule5.delete()