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.

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