test_signed_seer_api.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. from unittest.mock import MagicMock, Mock, patch
  2. import pytest
  3. from django.test import override_settings
  4. from sentry.seer.signed_seer_api import make_signed_seer_api_request
  5. from sentry.testutils.helpers import override_options
  6. REQUEST_BODY = b'{"b": 12, "thing": "thing"}'
  7. PATH = "/v0/some/url"
  8. def run_test_case(
  9. path: str = PATH,
  10. timeout: int | None = None,
  11. shared_secret: str = "secret-one",
  12. ):
  13. """
  14. Make a mock connection pool, call `make_signed_seer_api_request` on it, and return the
  15. pool's `urlopen` method, so we can make assertions on how `make_signed_seer_api_request`
  16. used it.
  17. """
  18. mock = Mock()
  19. mock.host = "localhost"
  20. mock.port = None
  21. mock.scheme = "http"
  22. with override_settings(SEER_API_SHARED_SECRET=shared_secret):
  23. make_signed_seer_api_request(
  24. mock,
  25. path=path,
  26. body=REQUEST_BODY,
  27. timeout=timeout,
  28. )
  29. return mock.urlopen
  30. @pytest.mark.django_db
  31. def test_simple():
  32. mock_url_open = run_test_case()
  33. mock_url_open.assert_called_once_with(
  34. "POST",
  35. PATH,
  36. body=REQUEST_BODY,
  37. headers={"content-type": "application/json;charset=utf-8"},
  38. )
  39. @pytest.mark.django_db
  40. def test_uses_given_timeout():
  41. mock_url_open = run_test_case(timeout=5)
  42. mock_url_open.assert_called_once_with(
  43. "POST",
  44. PATH,
  45. body=REQUEST_BODY,
  46. headers={"content-type": "application/json;charset=utf-8"},
  47. timeout=5,
  48. )
  49. @pytest.mark.django_db
  50. def test_uses_shared_secret():
  51. with override_options({"seer.api.use-shared-secret": 1.0}):
  52. mock_url_open = run_test_case()
  53. mock_url_open.assert_called_once_with(
  54. "POST",
  55. PATH,
  56. body=REQUEST_BODY,
  57. headers={
  58. "content-type": "application/json;charset=utf-8",
  59. "Authorization": "Rpcsignature rpc0:d2e6070dfab955db6fc9f3bc0518f75f27ca93ae2e393072929e5f6cba26ff07",
  60. },
  61. )
  62. @pytest.mark.django_db
  63. def test_uses_shared_secret_missing_secret():
  64. with override_options({"seer.api.use-shared-secret": 1.0}):
  65. mock_url_open = run_test_case(shared_secret="")
  66. mock_url_open.assert_called_once_with(
  67. "POST",
  68. PATH,
  69. body=REQUEST_BODY,
  70. headers={"content-type": "application/json;charset=utf-8"},
  71. )
  72. @pytest.mark.django_db
  73. @pytest.mark.parametrize("path", [PATH, f"{PATH}?dogs=great"])
  74. @patch("sentry.seer.signed_seer_api.metrics.timer")
  75. def test_times_request(mock_metrics_timer: MagicMock, path: str):
  76. run_test_case(path=path)
  77. mock_metrics_timer.assert_called_with(
  78. "seer.request_to_seer",
  79. sample_rate=1.0,
  80. tags={
  81. # In both cases the path is the same, because query params are stripped
  82. "endpoint": PATH,
  83. },
  84. )