test_minidump_full.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. from __future__ import absolute_import
  2. import time
  3. import pytest
  4. import zipfile
  5. from sentry.utils.compat.mock import patch
  6. from six import BytesIO
  7. from django.core.urlresolvers import reverse
  8. from django.core.files.uploadedfile import SimpleUploadedFile
  9. from sentry import eventstore
  10. from sentry.testutils import TransactionTestCase, RelayStoreHelper
  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. class SymbolicatorMinidumpIntegrationTest(RelayStoreHelper, TransactionTestCase):
  18. @pytest.fixture(autouse=True)
  19. def initialize(self, live_server):
  20. self.project.update_option("sentry:builtin_symbol_sources", [])
  21. new_prefix = live_server.url
  22. with patch("sentry.auth.system.is_internal_ip", return_value=True), self.options(
  23. {"system.url-prefix": new_prefix}
  24. ):
  25. # Run test case:
  26. yield
  27. def upload_symbols(self):
  28. url = reverse(
  29. "sentry-api-0-dsym-files",
  30. kwargs={
  31. "organization_slug": self.project.organization.slug,
  32. "project_slug": self.project.slug,
  33. },
  34. )
  35. self.login_as(user=self.user)
  36. out = BytesIO()
  37. f = zipfile.ZipFile(out, "w")
  38. f.write(get_fixture_path("windows.sym"), "crash.sym")
  39. f.close()
  40. response = self.client.post(
  41. url,
  42. {
  43. "file": SimpleUploadedFile(
  44. "symbols.zip", out.getvalue(), content_type="application/zip"
  45. )
  46. },
  47. format="multipart",
  48. )
  49. assert response.status_code == 201, response.content
  50. assert len(response.data) == 1
  51. def test_full_minidump(self):
  52. self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
  53. self.upload_symbols()
  54. with self.feature("organizations:event-attachments"):
  55. with open(get_fixture_path("windows.dmp"), "rb") as f:
  56. event = self.post_and_retrieve_minidump(
  57. {
  58. "upload_file_minidump": f,
  59. "some_file": ("hello.txt", BytesIO(b"Hello World!")),
  60. },
  61. {"sentry[logger]": "test-logger"},
  62. )
  63. insta_snapshot_stacktrace_data(self, event.data)
  64. assert event.data.get("logger") == "test-logger"
  65. # assert event.data.get("extra") == {"foo": "bar"}
  66. attachments = sorted(
  67. EventAttachment.objects.filter(event_id=event.event_id), key=lambda x: x.name
  68. )
  69. hello, minidump = attachments
  70. assert hello.name == "hello.txt"
  71. assert hello.file.type == "event.attachment"
  72. assert hello.file.checksum == "2ef7bde608ce5404e97d5f042f95f89f1c232871"
  73. assert minidump.name == "windows.dmp"
  74. assert minidump.file.type == "event.minidump"
  75. assert minidump.file.checksum == "74bb01c850e8d65d3ffbc5bad5cabc4668fce247"
  76. def test_full_minidump_json_extra(self):
  77. self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
  78. self.upload_symbols()
  79. with self.feature("organizations:event-attachments"):
  80. with open(get_fixture_path("windows.dmp"), "rb") as f:
  81. event = self.post_and_retrieve_minidump(
  82. {"upload_file_minidump": f},
  83. {"sentry": '{"logger":"test-logger"}', "foo": "bar"},
  84. )
  85. assert event.data.get("logger") == "test-logger"
  86. assert event.data.get("extra") == {"foo": "bar"}
  87. # Other assertions are performed by `test_full_minidump`
  88. def test_full_minidump_invalid_extra(self):
  89. self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
  90. self.upload_symbols()
  91. with self.feature("organizations:event-attachments"):
  92. with open(get_fixture_path("windows.dmp"), "rb") as f:
  93. event = self.post_and_retrieve_minidump(
  94. {"upload_file_minidump": f},
  95. {"sentry": "{{{{", "foo": "bar"}, # invalid sentry JSON
  96. )
  97. assert not event.data.get("logger")
  98. assert event.data.get("extra") == {"foo": "bar"}
  99. # Other assertions are performed by `test_full_minidump`
  100. def test_missing_dsym(self):
  101. with self.feature("organizations:event-attachments"):
  102. with open(get_fixture_path("windows.dmp"), "rb") as f:
  103. event = self.post_and_retrieve_minidump(
  104. {"upload_file_minidump": f}, {"sentry[logger]": "test-logger"}
  105. )
  106. insta_snapshot_stacktrace_data(self, event.data)
  107. assert not EventAttachment.objects.filter(event_id=event.event_id)
  108. def test_reprocessing(self):
  109. self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
  110. with self.feature(
  111. {"organizations:event-attachments": True, "projects:reprocessing-v2": True}
  112. ):
  113. with open(get_fixture_path("windows.dmp"), "rb") as f:
  114. event = self.post_and_retrieve_minidump(
  115. {"upload_file_minidump": f}, {"sentry[logger]": "test-logger"}
  116. )
  117. insta_snapshot_stacktrace_data(self, event.data, subname="initial")
  118. self.upload_symbols()
  119. from sentry.tasks.reprocessing2 import reprocess_event
  120. with self.tasks():
  121. reprocess_event.delay(
  122. project_id=self.project.id, event_id=event.event_id, start_time=time.time()
  123. )
  124. (new_event,) = eventstore.get_events(
  125. eventstore.Filter(
  126. project_ids=[self.project.id],
  127. conditions=[["tags[original_event_id]", "=", event.event_id]],
  128. )
  129. )
  130. assert new_event is not None
  131. assert new_event.event_id != event.event_id
  132. insta_snapshot_stacktrace_data(self, new_event.data, subname="reprocessed")
  133. for event_id in (event.event_id, new_event.event_id):
  134. (minidump,) = sorted(
  135. EventAttachment.objects.filter(event_id=new_event.event_id), key=lambda x: x.name
  136. )
  137. assert minidump.name == "windows.dmp"
  138. assert minidump.file.type == "event.minidump"
  139. assert minidump.file.checksum == "74bb01c850e8d65d3ffbc5bad5cabc4668fce247"