test_devservices_healthcheck.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import subprocess
  2. import time
  3. from typing import Generator, List
  4. from unittest import mock
  5. import pytest
  6. from tools.devservices_healthcheck import HealthcheckError, check_health, run_with_retries
  7. @pytest.fixture(autouse=True)
  8. def no_sleep() -> Generator[None, None, None]:
  9. with mock.patch.object(time, "sleep"):
  10. yield
  11. @pytest.fixture
  12. def mock_subprocess_run() -> Generator[mock.Mock, None, None]:
  13. with mock.patch.object(subprocess, "run", autospec=True) as mock_run:
  14. yield mock_run
  15. def test_run_with_retries_fail() -> None:
  16. with pytest.raises(HealthcheckError):
  17. run_with_retries(
  18. lambda: subprocess.run(("ls", "/tmp/this-does-not-exist"), check=True), 1, 10
  19. )
  20. def test_run_with_retries_ok() -> None:
  21. run_with_retries(lambda: subprocess.run("date", check=True), 1, 10)
  22. def test_postgres_not_running(mock_subprocess_run: mock.MagicMock) -> None:
  23. mock_subprocess_run.return_value.stdout = ""
  24. mock_subprocess_run.return_value.code = 0
  25. with pytest.raises(HealthcheckError):
  26. check_health(["postgres"])
  27. assert mock_subprocess_run.call_count == 3
  28. def test_postgres_healthcheck_failing(mock_subprocess_run: mock.MagicMock) -> None:
  29. running = mock.Mock()
  30. running.stdout = "running\n"
  31. running.code = 0
  32. mock_subprocess_run.side_effect = [
  33. running,
  34. HealthcheckError("injected error"),
  35. HealthcheckError("injected error"),
  36. HealthcheckError("injected error"),
  37. ]
  38. with pytest.raises(HealthcheckError):
  39. check_health(["postgres"])
  40. assert mock_subprocess_run.call_count == 4
  41. def test_postgres_running(mock_subprocess_run: mock.MagicMock) -> None:
  42. running = mock.Mock()
  43. running.stdout = "running\n"
  44. running.code = 0
  45. healthcheck = mock.Mock()
  46. mock_subprocess_run.side_effect = [
  47. running,
  48. healthcheck,
  49. ]
  50. check_health(["postgres"])
  51. assert mock_subprocess_run.call_count == 2
  52. def test_kafka_zookeper_running(mock_subprocess_run: mock.MagicMock) -> None:
  53. running = mock.Mock()
  54. running.stdout = "running\n"
  55. running.code = 0
  56. healthcheck = mock.Mock()
  57. def run(
  58. cmd_args: List[str], capture_output: bool = False, text: bool = False, check: bool = False
  59. ) -> mock.Mock:
  60. if cmd_args == (
  61. "docker",
  62. "container",
  63. "inspect",
  64. "-f",
  65. "{{.State.Status}}",
  66. "sentry_zookeeper",
  67. ):
  68. return running
  69. elif cmd_args == (
  70. "docker",
  71. "container",
  72. "inspect",
  73. "-f",
  74. "{{.State.Status}}",
  75. "sentry_kafka",
  76. ):
  77. return running
  78. elif cmd_args == (
  79. "docker",
  80. "exec",
  81. "sentry_kafka",
  82. "kafka-topics",
  83. "--zookeeper",
  84. "sentry_zookeeper:2181",
  85. "--list",
  86. ) or (
  87. "docker",
  88. "exec",
  89. "sentry_kafka",
  90. "kafka-topics",
  91. "--zookeeper",
  92. "127.0.0.1:2181",
  93. "--list",
  94. ):
  95. return healthcheck
  96. raise AssertionError(f"unexpected command '{cmd_args}'")
  97. mock_subprocess_run.side_effect = run
  98. check_health(["kafka"])
  99. assert mock_subprocess_run.call_count == 3