Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/sentry_database.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ static bool
write_envelope(const sentry_path_t *path, const sentry_envelope_t *envelope)
{
sentry_uuid_t event_id = sentry__envelope_get_event_id(envelope);

// Generate a random UUID for the filename if the envelope has no event_id
// this avoids collisions on NIL-UUIDs
if (sentry_uuid_is_nil(&event_id)) {
event_id = sentry_uuid_new_v4();
}

char *envelope_filename = sentry__uuid_as_filename(&event_id, ".envelope");
if (!envelope_filename) {
return false;
Expand Down
15 changes: 15 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ def split_log_request_cond(httpserver_log, cond):
)


def extract_request(httpserver_log, cond):
"""
Extract a request matching the condition from the httpserver log.
Returns (matching_request, remaining_log_entries)

The remaining_log_entries preserves the original format so it can be
chained with subsequent extract_request calls.
"""
for i, entry in enumerate(httpserver_log):
if cond(entry[0].get_data()):
others = [httpserver_log[j] for j in range(len(httpserver_log)) if j != i]
return (entry[0], others)
return (None, httpserver_log)


def run(cwd, exe, args, expect_failure=False, env=None, **kwargs):
if env is None:
env = dict(os.environ)
Expand Down
37 changes: 37 additions & 0 deletions tests/test_integration_crashpad.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
run,
Envelope,
split_log_request_cond,
extract_request,
is_session_envelope,
is_logs_envelope,
is_feedback_envelope,
Expand Down Expand Up @@ -614,6 +615,42 @@ def test_crashpad_logs_on_crash(cmake, httpserver):
assert_logs(logs_envelope, 1)


@pytest.mark.skipif(not flushes_state, reason="test needs state flushing")
def test_crashpad_logs_and_session_on_crash(cmake, httpserver):
tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "crashpad"})

env = dict(os.environ, SENTRY_DSN=make_dsn(httpserver))
httpserver.expect_oneshot_request("/api/123456/minidump/").respond_with_data("OK")
httpserver.expect_request("/api/123456/envelope/").respond_with_data("OK")

with httpserver.wait(timeout=10) as waiting:
run(
tmp_path,
"sentry_example",
["log", "enable-logs", "capture-log", "crash", "start-session"],
expect_failure=True,
env=env,
)

assert waiting.result

run(tmp_path, "sentry_example", ["log", "no-setup"], env=env)

# we expect 1 envelope with the log, 1 for the crash, and 1 for the session
assert len(httpserver.log) == 3

logs_request, remaining = extract_request(httpserver.log, is_logs_envelope)
session_request, remaining = extract_request(remaining, is_session_envelope)
multipart = remaining[0][0] # The crash/minidump

logs_envelope = Envelope.deserialize(logs_request.get_data())
assert logs_envelope is not None
assert_logs(logs_envelope, 1)

session_envelope = Envelope.deserialize(session_request.get_data())
assert session_envelope is not None


def test_disable_backend(cmake, httpserver):
tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "crashpad"})

Expand Down
Loading