Files
update-server/tests/test_crash_api.py
T

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))