You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
8.2 KiB

8 years ago
8 years ago
6 years ago
  1. from datetime import datetime, timedelta
  2. from unittest.mock import patch
  3. from django.utils import timezone
  4. from hc.api.models import Check, Flip
  5. from hc.test import BaseTestCase
  6. class CheckModelTestCase(BaseTestCase):
  7. def test_it_strips_tags(self):
  8. check = Check()
  9. check.tags = " foo bar "
  10. self.assertEqual(check.tags_list(), ["foo", "bar"])
  11. check.tags = " "
  12. self.assertEqual(check.tags_list(), [])
  13. def test_get_status_handles_new_check(self):
  14. check = Check()
  15. self.assertEqual(check.get_status(), "new")
  16. def test_status_works_with_grace_period(self):
  17. check = Check()
  18. check.status = "up"
  19. check.last_ping = timezone.now() - timedelta(days=1, minutes=30)
  20. self.assertEqual(check.get_status(), "grace")
  21. def test_get_status_handles_paused_check(self):
  22. check = Check()
  23. check.status = "up"
  24. check.last_ping = timezone.now() - timedelta(days=1, minutes=30)
  25. self.assertEqual(check.get_status(), "grace")
  26. check.status = "paused"
  27. self.assertEqual(check.get_status(), "paused")
  28. def test_status_works_with_cron_syntax(self):
  29. dt = timezone.make_aware(datetime(2000, 1, 1), timezone=timezone.utc)
  30. # Expect ping every midnight, default grace is 1 hour
  31. check = Check()
  32. check.kind = "cron"
  33. check.schedule = "0 0 * * *"
  34. check.status = "up"
  35. check.last_ping = dt
  36. # 23:59pm
  37. now = dt + timedelta(hours=23, minutes=59)
  38. self.assertEqual(check.get_status(now), "up")
  39. # 00:00am
  40. now = dt + timedelta(days=1)
  41. self.assertEqual(check.get_status(now), "grace")
  42. # 1:30am
  43. now = dt + timedelta(days=1, minutes=60)
  44. self.assertEqual(check.get_status(now), "down")
  45. def test_status_works_with_timezone(self):
  46. dt = timezone.make_aware(datetime(2000, 1, 1), timezone=timezone.utc)
  47. # Expect ping every day at 10am, default grace is 1 hour
  48. check = Check()
  49. check.kind = "cron"
  50. check.schedule = "0 10 * * *"
  51. check.status = "up"
  52. check.last_ping = dt
  53. check.tz = "Australia/Brisbane" # UTC+10
  54. # 10:30am
  55. now = dt + timedelta(hours=23, minutes=59)
  56. self.assertEqual(check.get_status(now), "up")
  57. # 10:30am
  58. now = dt + timedelta(days=1)
  59. self.assertEqual(check.get_status(now), "grace")
  60. # 11:30am
  61. now = dt + timedelta(days=1, minutes=60)
  62. self.assertEqual(check.get_status(now), "down")
  63. def test_get_status_handles_past_grace(self):
  64. check = Check()
  65. check.status = "up"
  66. check.last_ping = timezone.now() - timedelta(days=2)
  67. self.assertEqual(check.get_status(), "down")
  68. def test_get_status_obeys_down_status(self):
  69. check = Check()
  70. check.status = "down"
  71. check.last_ping = timezone.now() - timedelta(minutes=1)
  72. self.assertEqual(check.get_status(), "down")
  73. def test_get_status_handles_started(self):
  74. check = Check()
  75. check.last_ping = timezone.now() - timedelta(hours=2)
  76. # Last start was 5 minutes ago, display status should be "started"
  77. check.last_start = timezone.now() - timedelta(minutes=5)
  78. for status in ("new", "paused", "up", "down"):
  79. check.status = status
  80. self.assertEqual(check.get_status(), "started")
  81. def test_get_status_handles_down_then_started_and_expired(self):
  82. check = Check(status="down")
  83. # Last ping was 2 days ago
  84. check.last_ping = timezone.now() - timedelta(days=2)
  85. # Last start was 2 hours ago - the check is past its grace time
  86. check.last_start = timezone.now() - timedelta(hours=2)
  87. self.assertEqual(check.get_status(), "down")
  88. self.assertEqual(check.get_status(with_started=False), "down")
  89. def test_get_status_handles_up_then_started(self):
  90. check = Check(status="up")
  91. # Last ping was 2 hours ago, so is still up
  92. check.last_ping = timezone.now() - timedelta(hours=2)
  93. # Last start was 5 minutes ago
  94. check.last_start = timezone.now() - timedelta(minutes=5)
  95. self.assertEqual(check.get_status(), "started")
  96. # Starting a check starts the grace period:
  97. self.assertEqual(check.get_status(with_started=False), "grace")
  98. def test_get_status_handles_up_then_started_and_expired(self):
  99. check = Check(status="up")
  100. # Last ping was 3 hours ago, so is still up
  101. check.last_ping = timezone.now() - timedelta(hours=3)
  102. # Last start was 2 hours ago - the check is past its grace time
  103. check.last_start = timezone.now() - timedelta(hours=2)
  104. self.assertEqual(check.get_status(), "down")
  105. self.assertEqual(check.get_status(with_started=False), "down")
  106. def test_get_status_handles_paused_then_started_and_expired(self):
  107. check = Check(status="paused")
  108. # Last start was 2 hours ago - the check is past its grace time
  109. check.last_start = timezone.now() - timedelta(hours=2)
  110. self.assertEqual(check.get_status(), "down")
  111. self.assertEqual(check.get_status(with_started=False), "down")
  112. def test_get_status_handles_started_and_mia(self):
  113. check = Check()
  114. check.last_start = timezone.now() - timedelta(hours=2)
  115. self.assertEqual(check.get_status(), "down")
  116. self.assertEqual(check.get_status(with_started=False), "down")
  117. def test_next_ping_with_cron_syntax(self):
  118. dt = timezone.make_aware(datetime(2000, 1, 1), timezone=timezone.utc)
  119. # Expect ping every round hour
  120. check = Check(project=self.project)
  121. check.kind = "cron"
  122. check.schedule = "0 * * * *"
  123. check.status = "up"
  124. check.last_ping = dt
  125. # Need to save it for M2M relations to work:
  126. check.save()
  127. d = check.to_dict()
  128. self.assertEqual(d["next_ping"], "2000-01-01T01:00:00+00:00")
  129. def test_downtimes_handles_no_flips(self):
  130. check = Check.objects.create(project=self.project)
  131. r = check.downtimes(10)
  132. self.assertEqual(len(r), 10)
  133. for dt, downtime, outages in r:
  134. self.assertEqual(downtime.total_seconds(), 0)
  135. self.assertEqual(outages, 0)
  136. def test_downtimes_handles_currently_down_check(self):
  137. check = Check.objects.create(project=self.project, status="down")
  138. r = check.downtimes(10)
  139. self.assertEqual(len(r), 10)
  140. for dt, downtime, outages in r:
  141. self.assertEqual(outages, 1)
  142. @patch("hc.api.models.timezone.now")
  143. def test_downtimes_handles_flip_one_day_ago(self, mock_now):
  144. mock_now.return_value = datetime(2019, 7, 19, tzinfo=timezone.utc)
  145. check = Check.objects.create(project=self.project, status="down")
  146. flip = Flip(owner=check)
  147. flip.created = datetime(2019, 7, 18, tzinfo=timezone.utc)
  148. flip.old_status = "up"
  149. flip.new_status = "down"
  150. flip.save()
  151. r = check.downtimes(10)
  152. self.assertEqual(len(r), 10)
  153. for dt, downtime, outages in r:
  154. if dt.month == 7:
  155. self.assertEqual(downtime.total_seconds(), 86400)
  156. self.assertEqual(outages, 1)
  157. else:
  158. self.assertEqual(downtime.total_seconds(), 0)
  159. self.assertEqual(outages, 0)
  160. @patch("hc.api.models.timezone.now")
  161. def test_downtimes_handles_flip_two_months_ago(self, mock_now):
  162. mock_now.return_value = datetime(2019, 7, 19, tzinfo=timezone.utc)
  163. check = Check.objects.create(project=self.project, status="down")
  164. flip = Flip(owner=check)
  165. flip.created = datetime(2019, 5, 19, tzinfo=timezone.utc)
  166. flip.old_status = "up"
  167. flip.new_status = "down"
  168. flip.save()
  169. r = check.downtimes(10)
  170. self.assertEqual(len(r), 10)
  171. for dt, downtime, outages in r:
  172. if dt.month == 7:
  173. self.assertEqual(outages, 1)
  174. elif dt.month == 6:
  175. self.assertEqual(downtime.total_seconds(), 30 * 86400)
  176. self.assertEqual(outages, 1)
  177. elif dt.month == 5:
  178. self.assertEqual(outages, 1)
  179. else:
  180. self.assertEqual(downtime.total_seconds(), 0)
  181. self.assertEqual(outages, 0)