test_payload_full.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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 File, ProjectDebugFile
  12. from sentry.testutils.helpers.datetime import iso_format, before_now
  13. from sentry.utils import json
  14. from tests.symbolicator import get_fixture_path, insta_snapshot_stacktrace_data
  15. # IMPORTANT:
  16. # For these tests to run, write `symbolicator.enabled: true` into your
  17. # `~/.sentry/config.yml` and run `sentry devservices up`
  18. REAL_RESOLVING_EVENT_DATA = {
  19. "platform": "cocoa",
  20. "debug_meta": {
  21. "images": [
  22. {
  23. "type": "apple",
  24. "arch": "x86_64",
  25. "uuid": "502fc0a5-1ec1-3e47-9998-684fa139dca7",
  26. "image_vmaddr": "0x0000000100000000",
  27. "image_size": 4096,
  28. "image_addr": "0x0000000100000000",
  29. "name": "Foo.app/Contents/Foo",
  30. }
  31. ],
  32. "sdk_info": {
  33. "dsym_type": "macho",
  34. "sdk_name": "macOS",
  35. "version_major": 10,
  36. "version_minor": 12,
  37. "version_patchlevel": 4,
  38. },
  39. },
  40. "exception": {
  41. "values": [
  42. {
  43. "stacktrace": {
  44. "frames": [
  45. {"platform": "foobar", "function": "hi"},
  46. {"function": "unknown", "instruction_addr": "0x0000000100000fa0"},
  47. ]
  48. },
  49. "type": "Fail",
  50. "value": "fail",
  51. }
  52. ]
  53. },
  54. "timestamp": iso_format(before_now(seconds=1)),
  55. }
  56. class ResolvingIntegrationTestBase(object):
  57. def get_event(self, event_id):
  58. return eventstore.get_event_by_id(self.project.id, event_id)
  59. def test_real_resolving(self):
  60. url = reverse(
  61. "sentry-api-0-dsym-files",
  62. kwargs={
  63. "organization_slug": self.project.organization.slug,
  64. "project_slug": self.project.slug,
  65. },
  66. )
  67. self.login_as(user=self.user)
  68. out = BytesIO()
  69. f = zipfile.ZipFile(out, "w")
  70. f.write(get_fixture_path("hello.dsym"), "dSYM/hello")
  71. f.close()
  72. response = self.client.post(
  73. url,
  74. {
  75. "file": SimpleUploadedFile(
  76. "symbols.zip", out.getvalue(), content_type="application/zip"
  77. )
  78. },
  79. format="multipart",
  80. )
  81. assert response.status_code == 201, response.content
  82. assert len(response.data) == 1
  83. resp = self._postWithHeader(dict(project=self.project.id, **REAL_RESOLVING_EVENT_DATA))
  84. assert resp.status_code == 200
  85. event = self.get_event(json.loads(resp.content)["id"])
  86. assert event.data["culprit"] == "main"
  87. insta_snapshot_stacktrace_data(self, event.data)
  88. def test_debug_id_resolving(self):
  89. file = File.objects.create(
  90. name="crash.pdb", type="default", headers={"Content-Type": "text/x-breakpad"}
  91. )
  92. path = get_fixture_path("windows.sym")
  93. with open(path) as f:
  94. file.putfile(f)
  95. ProjectDebugFile.objects.create(
  96. file=file,
  97. object_name="crash.pdb",
  98. cpu_name="x86",
  99. project=self.project,
  100. debug_id="3249d99d-0c40-4931-8610-f4e4fb0b6936-1",
  101. code_id="5AB380779000",
  102. )
  103. self.login_as(user=self.user)
  104. event_data = {
  105. "contexts": {
  106. "device": {"arch": "x86"},
  107. "os": {"build": u"", "name": "Windows", "type": "os", "version": u"10.0.14393"},
  108. },
  109. "debug_meta": {
  110. "images": [
  111. {
  112. "id": u"3249d99d-0c40-4931-8610-f4e4fb0b6936-1",
  113. "image_addr": "0x2a0000",
  114. "image_size": 36864,
  115. "name": u"C:\\projects\\breakpad-tools\\windows\\Release\\crash.exe",
  116. "type": "symbolic",
  117. }
  118. ]
  119. },
  120. "exception": {
  121. "stacktrace": {
  122. "frames": [
  123. {
  124. "function": "<unknown>",
  125. "instruction_addr": "0x2a2a3d",
  126. "package": u"C:\\projects\\breakpad-tools\\windows\\Release\\crash.exe",
  127. }
  128. ]
  129. },
  130. "thread_id": 1636,
  131. "type": u"EXCEPTION_ACCESS_VIOLATION_WRITE",
  132. "value": u"Fatal Error: EXCEPTION_ACCESS_VIOLATION_WRITE",
  133. },
  134. "platform": "native",
  135. "timestamp": iso_format(before_now(seconds=1)),
  136. }
  137. resp = self._postWithHeader(event_data)
  138. assert resp.status_code == 200
  139. event = self.get_event(json.loads(resp.content)["id"])
  140. assert event.data["culprit"] == "main"
  141. insta_snapshot_stacktrace_data(self, event.data)
  142. def test_missing_dsym(self):
  143. self.login_as(user=self.user)
  144. resp = self._postWithHeader(dict(project=self.project.id, **REAL_RESOLVING_EVENT_DATA))
  145. assert resp.status_code == 200
  146. event = self.get_event(json.loads(resp.content)["id"])
  147. assert event.data["culprit"] == "unknown"
  148. insta_snapshot_stacktrace_data(self, event.data)
  149. def test_missing_debug_images(self):
  150. self.login_as(user=self.user)
  151. payload = dict(project=self.project.id, **REAL_RESOLVING_EVENT_DATA)
  152. del payload["debug_meta"]
  153. resp = self._postWithHeader(payload)
  154. assert resp.status_code == 200
  155. event = self.get_event(json.loads(resp.content)["id"])
  156. assert event.data["culprit"] == "unknown"
  157. insta_snapshot_stacktrace_data(self, event.data)
  158. @override_settings(ALLOWED_HOSTS=["localhost", "testserver", "host.docker.internal"])
  159. class SymbolicatorResolvingIntegrationTest(ResolvingIntegrationTestBase, TransactionTestCase):
  160. # For these tests to run, write `symbolicator.enabled: true` into your
  161. # `~/.sentry/config.yml` and run `sentry devservices up`
  162. @pytest.fixture(autouse=True)
  163. def initialize(self, live_server):
  164. self.project.update_option("sentry:builtin_symbol_sources", [])
  165. new_prefix = live_server.url
  166. with patch("sentry.auth.system.is_internal_ip", return_value=True), self.options(
  167. {"system.url-prefix": new_prefix}
  168. ):
  169. # Run test case:
  170. yield