114 lines
3.6 KiB
Python
114 lines
3.6 KiB
Python
import hashlib
|
|
import io
|
|
import json
|
|
from types import SimpleNamespace
|
|
import uuid
|
|
|
|
|
|
def crash_metadata(client_report_id: str, minidump: bytes):
|
|
return {
|
|
"schemaVersion": 1,
|
|
"clientReportId": client_report_id,
|
|
"crashTimeUtc": "2026-07-16T00:00:00Z",
|
|
"product": "SIMCAE",
|
|
"appVersion": "1.0.0",
|
|
"gitCommit": "test-commit",
|
|
"buildType": "Release",
|
|
"channel": "stable",
|
|
"platform": {"os": "Windows", "arch": "x64"},
|
|
"crash": {"exceptionCode": "0xC0000005"},
|
|
"userConsent": {"upload": True},
|
|
"files": [
|
|
{
|
|
"kind": "minidump",
|
|
"name": "crash.dmp",
|
|
"sha256": hashlib.sha256(minidump).hexdigest(),
|
|
}
|
|
],
|
|
}
|
|
|
|
|
|
class FakeHeaders(dict):
|
|
def __init__(self, values: dict[str, str]):
|
|
super().__init__((key.lower(), value) for key, value in values.items())
|
|
|
|
def get(self, key: str, default=None):
|
|
return super().get(key.lower(), default)
|
|
|
|
|
|
class FakeUpload:
|
|
def __init__(self, filename: str, data: bytes):
|
|
self.filename = filename
|
|
self._stream = io.BytesIO(data)
|
|
|
|
async def read(self, size: int = -1) -> bytes:
|
|
return self._stream.read(size)
|
|
|
|
|
|
class FakeMultipartRequest:
|
|
def __init__(self, headers: dict[str, str], form: dict, host: str = "127.0.0.1"):
|
|
self.headers = FakeHeaders(headers)
|
|
self._form = form
|
|
self.client = SimpleNamespace(host=host)
|
|
|
|
async def form(self):
|
|
return self._form
|
|
|
|
|
|
async def run_crash_report_upload_detail_and_duplicate(server_module):
|
|
async with server_module.lifespan(server_module.app):
|
|
from app.services import crash_api_service
|
|
|
|
minidump = b"fake minidump bytes"
|
|
client_report_id = str(uuid.uuid4())
|
|
metadata = crash_metadata(client_report_id, minidump)
|
|
metadata_bytes = json.dumps(metadata).encode()
|
|
headers = {
|
|
"Authorization": "Bearer CrashReportTokenForTests2026",
|
|
"Idempotency-Key": client_report_id,
|
|
"Content-Type": "multipart/form-data; boundary=test",
|
|
"Content-Length": str(len(metadata_bytes) + len(minidump)),
|
|
"X-SimCAE-Client": "SIMCAE",
|
|
"X-SimCAE-Version": "1.0.0",
|
|
}
|
|
|
|
upload = await crash_api_service.create_crash_report(
|
|
FakeMultipartRequest(
|
|
headers,
|
|
{
|
|
"metadata": FakeUpload("metadata.json", metadata_bytes),
|
|
"minidump": FakeUpload("crash.dmp", minidump),
|
|
},
|
|
)
|
|
)
|
|
assert upload.status_code == 201
|
|
upload_body = json.loads(upload.body)
|
|
report_id = upload_body["reportId"]
|
|
|
|
duplicate = await crash_api_service.create_crash_report(
|
|
FakeMultipartRequest(
|
|
headers,
|
|
{
|
|
"metadata": FakeUpload("metadata.json", metadata_bytes),
|
|
"minidump": FakeUpload("crash.dmp", minidump),
|
|
},
|
|
)
|
|
)
|
|
assert duplicate.status_code == 200
|
|
assert json.loads(duplicate.body)["duplicate"] is True
|
|
|
|
detail = crash_api_service.get_crash_report_detail(
|
|
report_id,
|
|
FakeMultipartRequest(
|
|
{"Authorization": "Bearer CrashAdminTokenForTests2026"},
|
|
{},
|
|
),
|
|
)
|
|
assert detail["clientReportId"] == client_report_id
|
|
|
|
|
|
def test_crash_report_upload_detail_and_duplicate(server_module):
|
|
import asyncio
|
|
|
|
asyncio.run(run_crash_report_upload_detail_and_duplicate(server_module))
|