test_minidump_full.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. from __future__ import absolute_import
  2. import pytest
  3. import zipfile
  4. from sentry.utils.compat.mock import patch
  5. from six import BytesIO
  6. from django.core.urlresolvers import reverse
  7. from django.core.files.uploadedfile import SimpleUploadedFile
  8. from django.test import override_settings
  9. from sentry import eventstore
  10. from sentry.testutils import TransactionTestCase
  11. from sentry.models import EventAttachment
  12. from sentry.lang.native.utils import STORE_CRASH_REPORTS_ALL
  13. from tests.symbolicator import get_fixture_path, insta_snapshot_stacktrace_data
  14. # IMPORTANT:
  15. # For these tests to run, write `symbolicator.enabled: true` into your
  16. # `~/.sentry/config.yml` and run `sentry devservices up`
  17. @override_settings(ALLOWED_HOSTS=["localhost", "testserver", "host.docker.internal"])
  18. class SymbolicatorMinidumpIntegrationTest(TransactionTestCase):
  19. @pytest.fixture(autouse=True)
  20. def initialize(self, live_server):
  21. self.project.update_option("sentry:builtin_symbol_sources", [])
  22. new_prefix = live_server.url
  23. with patch("sentry.auth.system.is_internal_ip", return_value=True), self.options(
  24. {"system.url-prefix": new_prefix}
  25. ):
  26. # Run test case:
  27. yield
  28. def upload_symbols(self):
  29. url = reverse(
  30. "sentry-api-0-dsym-files",
  31. kwargs={
  32. "organization_slug": self.project.organization.slug,
  33. "project_slug": self.project.slug,
  34. },
  35. )
  36. self.login_as(user=self.user)
  37. out = BytesIO()
  38. f = zipfile.ZipFile(out, "w")
  39. f.write(get_fixture_path("windows.sym"), "crash.sym")
  40. f.close()
  41. response = self.client.post(
  42. url,
  43. {
  44. "file": SimpleUploadedFile(
  45. "symbols.zip", out.getvalue(), content_type="application/zip"
  46. )
  47. },
  48. format="multipart",
  49. )
  50. assert response.status_code == 201, response.content
  51. assert len(response.data) == 1
  52. def test_full_minidump(self):
  53. self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
  54. self.upload_symbols()
  55. with self.feature("organizations:event-attachments"):
  56. attachment = BytesIO(b"Hello World!")
  57. attachment.name = "hello.txt"
  58. with open(get_fixture_path("windows.dmp"), "rb") as f:
  59. resp = self._postMinidumpWithHeader(
  60. f, {"sentry[logger]": "test-logger", "some_file": attachment}
  61. )
  62. assert resp.status_code == 200
  63. event_id = resp.content
  64. event = eventstore.get_event_by_id(self.project.id, event_id)
  65. insta_snapshot_stacktrace_data(self, event.data)
  66. assert event.data.get("logger") == "test-logger"
  67. # assert event.data.get("extra") == {"foo": "bar"}
  68. attachments = sorted(
  69. EventAttachment.objects.filter(event_id=event.event_id), key=lambda x: x.name
  70. )
  71. hello, minidump = attachments
  72. assert hello.name == "hello.txt"
  73. assert hello.file.type == "event.attachment"
  74. assert hello.file.checksum == "2ef7bde608ce5404e97d5f042f95f89f1c232871"
  75. assert minidump.name == "windows.dmp"
  76. assert minidump.file.type == "event.minidump"
  77. assert minidump.file.checksum == "74bb01c850e8d65d3ffbc5bad5cabc4668fce247"
  78. def test_full_minidump_json_extra(self):
  79. self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
  80. self.upload_symbols()
  81. with self.feature("organizations:event-attachments"):
  82. with open(get_fixture_path("windows.dmp"), "rb") as f:
  83. resp = self._postMinidumpWithHeader(
  84. f, {"sentry": '{"logger":"test-logger"}', "foo": "bar"}
  85. )
  86. assert resp.status_code == 200
  87. event_id = resp.content
  88. event = eventstore.get_event_by_id(self.project.id, event_id)
  89. assert event.data.get("logger") == "test-logger"
  90. assert event.data.get("extra") == {"foo": "bar"}
  91. # Other assertions are performed by `test_full_minidump`
  92. def test_full_minidump_invalid_extra(self):
  93. self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
  94. self.upload_symbols()
  95. with self.feature("organizations:event-attachments"):
  96. with open(get_fixture_path("windows.dmp"), "rb") as f:
  97. resp = self._postMinidumpWithHeader(
  98. f, {"sentry": "{{{{", "foo": "bar"} # invalid sentry JSON
  99. )
  100. assert resp.status_code == 200
  101. event_id = resp.content
  102. event = eventstore.get_event_by_id(self.project.id, event_id)
  103. assert not event.data.get("logger")
  104. assert event.data.get("extra") == {"foo": "bar"}
  105. # Other assertions are performed by `test_full_minidump`
  106. def test_raw_minidump(self):
  107. self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
  108. self.upload_symbols()
  109. with self.feature("organizations:event-attachments"):
  110. with open(get_fixture_path("windows.dmp"), "rb") as f:
  111. # Send as raw request body instead of multipart/form-data
  112. resp = self._postMinidumpWithHeader(f, raw=True)
  113. assert resp.status_code == 200
  114. event_id = resp.content
  115. event = eventstore.get_event_by_id(self.project.id, event_id)
  116. insta_snapshot_stacktrace_data(self, event.data)
  117. def test_missing_dsym(self):
  118. with self.feature("organizations:event-attachments"):
  119. with open(get_fixture_path("windows.dmp"), "rb") as f:
  120. resp = self._postMinidumpWithHeader(f, {"sentry[logger]": "test-logger"})
  121. assert resp.status_code == 200
  122. event_id = resp.content
  123. event = eventstore.get_event_by_id(self.project.id, event_id)
  124. insta_snapshot_stacktrace_data(self, event.data)
  125. assert not EventAttachment.objects.filter(event_id=event.event_id)