123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- import zipfile
- from io import BytesIO
- from unittest.mock import patch
- import pytest
- from django.core.files.uploadedfile import SimpleUploadedFile
- from django.urls import reverse
- from sentry.lang.native.utils import STORE_CRASH_REPORTS_ALL
- from sentry.models import EventAttachment, File
- from sentry.testutils import RelayStoreHelper, TransactionTestCase
- from sentry.testutils.factories import get_fixture_path
- from sentry.utils.safe import get_path
- from tests.symbolicator import normalize_native_exception
- # IMPORTANT:
- #
- # This test suite requires Symbolicator in order to run correctly.
- # Set `symbolicator.enabled: true` in your `~/.sentry/config.yml` and run `sentry devservices up`
- #
- # If you are using a local instance of Symbolicator, you need to
- # either change `system.url-prefix` option override inside `initialize` fixture to `system.internal-url-prefix`,
- # or add `127.0.0.1 host.docker.internal` entry to your `/etc/hosts`
- def get_unreal_crash_file():
- return get_fixture_path("native", "unreal_crash")
- def get_unreal_crash_apple_file():
- return get_fixture_path("native", "unreal_crash_apple")
- class SymbolicatorUnrealIntegrationTest(RelayStoreHelper, TransactionTestCase):
- @pytest.fixture(autouse=True)
- def initialize(self, live_server):
- self.project.update_option("sentry:builtin_symbol_sources", [])
- with patch("sentry.auth.system.is_internal_ip", return_value=True), self.options(
- {"system.url-prefix": live_server.url}
- ):
- # Run test case
- yield
- def upload_symbols(self):
- url = reverse(
- "sentry-api-0-dsym-files",
- kwargs={
- "organization_slug": self.project.organization.slug,
- "project_slug": self.project.slug,
- },
- )
- self.login_as(user=self.user)
- out = BytesIO()
- f = zipfile.ZipFile(out, "w")
- f.write(get_fixture_path("native", "unreal_crash.sym"), "crash.sym")
- f.close()
- response = self.client.post(
- url,
- {
- "file": SimpleUploadedFile(
- "symbols.zip", out.getvalue(), content_type="application/zip"
- )
- },
- format="multipart",
- )
- assert response.status_code == 201, response.content
- assert len(response.json()) == 1
- def unreal_crash_test_impl(self, filename):
- self.project.update_option("sentry:store_crash_reports", STORE_CRASH_REPORTS_ALL)
- self.upload_symbols()
- # attachments feature has to be on for the files extract stick around
- with self.feature("organizations:event-attachments"):
- with open(filename, "rb") as f:
- event = self.post_and_retrieve_unreal(f.read())
- self.insta_snapshot(
- {
- "contexts": event.data.get("contexts"),
- "exception": {
- "values": [
- normalize_native_exception(x)
- for x in get_path(event.data, "exception", "values") or ()
- ]
- },
- "stacktrace": event.data.get("stacktrace"),
- "threads": event.data.get("threads"),
- "extra": event.data.get("extra"),
- "sdk": event.data.get("sdk"),
- }
- )
- return sorted(EventAttachment.objects.filter(event_id=event.event_id), key=lambda x: x.name)
- def test_unreal_crash_with_attachments(self):
- attachments = self.unreal_crash_test_impl(get_unreal_crash_file())
- assert len(attachments) == 4
- context, config, minidump, log = attachments
- assert context.name == "CrashContext.runtime-xml"
- context_file = File.objects.get(id=context.file_id)
- assert context_file.type == "unreal.context"
- assert context_file.checksum == "835d3e10db5d1799dc625132c819c047261ddcfb"
- assert config.name == "CrashReportClient.ini"
- config_file = File.objects.get(id=config.file_id)
- assert config_file.type == "event.attachment"
- assert config_file.checksum == "5839c750bdde8cba4d2a979ea857b8154cffdab5"
- assert minidump.name == "UE4Minidump.dmp"
- minidump_file = File.objects.get(id=minidump.file_id)
- assert minidump_file.type == "event.minidump"
- assert minidump_file.checksum == "089d9fd3b5c0cc4426339ab46ec3835e4be83c0f"
- assert log.name == "YetAnother.log" # Log file is named after the project
- log_file = File.objects.get(id=log.file_id)
- assert log_file.type == "unreal.logs"
- assert log_file.checksum == "24d1c5f75334cd0912cc2670168d593d5fe6c081"
- def test_unreal_apple_crash_with_attachments(self):
- attachments = self.unreal_crash_test_impl(get_unreal_crash_apple_file())
- assert len(attachments) == 6
- context, config, diagnostics, log, info, minidump = attachments
- assert context.name == "CrashContext.runtime-xml"
- context_file = File.objects.get(id=context.file_id)
- assert context_file.type == "unreal.context"
- assert context_file.checksum == "5d2723a7d25111645702fcbbcb8e1d038db56c6e"
- assert config.name == "CrashReportClient.ini"
- config_file = File.objects.get(id=config.file_id)
- assert config_file.type == "event.attachment"
- assert config_file.checksum == "4d6a2736e3e4969a68b7adbe197b05c171c29ea0"
- assert diagnostics.name == "Diagnostics.txt"
- diagnostics_file = File.objects.get(id=diagnostics.file_id)
- assert diagnostics_file.type == "event.attachment"
- assert diagnostics_file.checksum == "aa271bf4e307a78005410234081945352e8fb236"
- assert log.name == "YetAnotherMac.log" # Log file is named after the project
- log_file = File.objects.get(id=log.file_id)
- assert log_file.type == "unreal.logs"
- assert log_file.checksum == "735e751a8b6b943dbc0abce0e6d096f4d48a0c1e"
- assert info.name == "info.txt"
- info_file = File.objects.get(id=info.file_id)
- assert info_file.type == "event.attachment"
- assert info_file.checksum == "279b27ac5d0e6792d088e0662ce1a18413b772bc"
- assert minidump.name == "minidump.dmp"
- minidump_file = File.objects.get(id=minidump.file_id)
- assert minidump_file.type == "event.applecrashreport"
- assert minidump_file.checksum == "728d0f4b09cf5a7942da3893b6db79ac842b701a"
|