mirror of
https://github.com/mvt-project/mvt.git
synced 2026-05-28 10:51:45 +02:00
Tombstone: fall back to file timestamp on empty pb timestamp
- Allow empty protobuf timestamps to fall back to the file timestamp - Update _parse_timestamp_string to accept a fallback - Pass file_timestamp to its callers - Add tests for empty and whitespace tombstone timestamps - Adjust imports in bugreport module to include DumpsysADBState Tombstone: use file timestamp on empty pb - skip 0 bytes tombstones and show debug warning
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
# Copyright (c) 2021-2023 The MVT Authors.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
import os
|
||||
import datetime
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -65,3 +65,89 @@ class TestTombstoneCrashArtifact:
|
||||
# MVT should output the local time only:
|
||||
# So original 2023-04-12 12:32:40.518290770+0200 -> 2023-04-12 12:32:40.000000
|
||||
assert tombstone_result.get("timestamp") == "2023-04-12 12:32:40.518290"
|
||||
|
||||
def test_tombstone_pb_empty_timestamp(self):
|
||||
"""Test parsing a protobuf tombstone with an empty timestamp."""
|
||||
tombstone_artifact = TombstoneCrashArtifact()
|
||||
artifact_path = "android_data/bugreport_tombstones/tombstone_empty_timestamp.pb"
|
||||
file = get_artifact(artifact_path)
|
||||
with open(file, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
file_name = os.path.basename(artifact_path)
|
||||
file_timestamp = datetime.datetime(2024, 1, 15, 10, 30, 45, 123456)
|
||||
tombstone_artifact.parse_protobuf(file_name, file_timestamp, data)
|
||||
|
||||
assert len(tombstone_artifact.results) == 1
|
||||
result = tombstone_artifact.results[0]
|
||||
|
||||
# When tombstone has empty timestamp, should use file modification time
|
||||
assert result.get("timestamp") == "2024-01-15 10:30:45.123456"
|
||||
assert result.get("pid") == 12345
|
||||
assert result.get("uid") == 1000
|
||||
assert result.get("signal_info", {}).get("name") == "SIGSEGV"
|
||||
|
||||
def test_tombstone_pb_empty_timestamp_with_threads(self):
|
||||
"""Test parsing a protobuf tombstone with empty timestamp and thread info."""
|
||||
tombstone_artifact = TombstoneCrashArtifact()
|
||||
artifact_path = "android_data/bugreport_tombstones/tombstone_empty_timestamp_with_threads.pb"
|
||||
file = get_artifact(artifact_path)
|
||||
with open(file, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
file_name = os.path.basename(artifact_path)
|
||||
file_timestamp = datetime.datetime(2024, 2, 20, 14, 15, 30, 0)
|
||||
tombstone_artifact.parse_protobuf(file_name, file_timestamp, data)
|
||||
|
||||
assert len(tombstone_artifact.results) == 1
|
||||
result = tombstone_artifact.results[0]
|
||||
|
||||
# Verify timestamp fallback
|
||||
assert result.get("timestamp") == "2024-02-20 14:15:30.000000"
|
||||
assert result.get("pid") == 9876
|
||||
assert result.get("uid") == 10001
|
||||
assert result.get("signal_info", {}).get("name") == "SIGABRT"
|
||||
assert result.get("process_name") == "ExampleThread"
|
||||
|
||||
def test_tombstone_pb_whitespace_timestamp(self):
|
||||
"""Test parsing a protobuf tombstone with whitespace-only timestamp."""
|
||||
tombstone_artifact = TombstoneCrashArtifact()
|
||||
artifact_path = (
|
||||
"android_data/bugreport_tombstones/tombstone_whitespace_timestamp.pb"
|
||||
)
|
||||
file = get_artifact(artifact_path)
|
||||
with open(file, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
file_name = os.path.basename(artifact_path)
|
||||
file_timestamp = datetime.datetime(2024, 3, 10, 8, 0, 0, 0)
|
||||
tombstone_artifact.parse_protobuf(file_name, file_timestamp, data)
|
||||
|
||||
assert len(tombstone_artifact.results) == 1
|
||||
result = tombstone_artifact.results[0]
|
||||
|
||||
# Verify whitespace timestamp is treated as empty
|
||||
assert result.get("timestamp") == "2024-03-10 08:00:00.000000"
|
||||
assert result.get("pid") == 11111
|
||||
assert result.get("uid") == 2000
|
||||
assert result.get("signal_info", {}).get("name") == "SIGILL"
|
||||
|
||||
def test_tombstone_pb_empty_file(self):
|
||||
"""Test that empty (0 bytes) tombstone files are handled gracefully."""
|
||||
tombstone_artifact = TombstoneCrashArtifact()
|
||||
artifact_path = "android_data/bugreport_tombstones/tombstone_empty_file.pb"
|
||||
file = get_artifact(artifact_path)
|
||||
with open(file, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
# Verify the file is actually empty
|
||||
assert len(data) == 0, "Test file should be empty (0 bytes)"
|
||||
|
||||
file_name = os.path.basename(artifact_path)
|
||||
file_timestamp = datetime.datetime(2024, 4, 1, 12, 0, 0, 0)
|
||||
|
||||
# Empty files should be skipped in the module (not parsed)
|
||||
# So we don't call parse_protobuf here, just verify the data is empty
|
||||
# The actual skipping happens in the Tombstones module's run() method
|
||||
# This test verifies that empty data is detectable
|
||||
assert len(data) == 0
|
||||
|
||||
Reference in New Issue
Block a user