Add iOS sysdiagnose checking

This commit is contained in:
Janik Besendorf
2026-07-14 21:42:03 +02:00
parent f5b0a3cd91
commit f2b58d4b73
13 changed files with 513 additions and 8 deletions
+9 -1
View File
@@ -50,6 +50,10 @@ class CustomIOSFSModule(RecordingModule):
supported_commands = (("ios", "check-fs"),)
class UnscopedCustomModule(RecordingModule):
pass
class CustomDependsOnBuiltin(RecordingModule):
supported_commands = (("ios", "check-backup"),)
dependencies = (FirstModule,)
@@ -151,7 +155,11 @@ class TestCommand:
cmd.platform = "ios"
cmd.name = "check-backup"
cmd.modules = [FirstModule]
cmd.custom_modules = [CustomIOSBackupModule, CustomIOSFSModule]
cmd.custom_modules = [
CustomIOSBackupModule,
CustomIOSFSModule,
UnscopedCustomModule,
]
assert [module.__name__ for module in cmd._ordered_modules()] == [
"FirstModule",
+4 -3
View File
@@ -125,12 +125,13 @@ def test_load_custom_modules_loads_env_folder_first(tmp_path, monkeypatch):
assert [module.__name__ for module in modules] == ["EnvModule", "CliModule"]
def test_module_supports_command_defaults_to_all_commands(tmp_path):
def test_module_supports_command_requires_explicit_declaration(tmp_path, caplog):
module_path = _write_module(tmp_path / "custom.py", "DefaultModule")
module = load_custom_modules_from_path(str(module_path))[0]
assert module_supports_command(module, "ios", "check-backup")
assert module_supports_command(module, "android", "check-bugreport")
assert not module_supports_command(module, "ios", "check-backup")
assert not module_supports_command(module, "android", "check-bugreport")
assert "DefaultModule has no supported_commands" in caplog.text
def test_module_supports_command_honors_supported_commands(tmp_path):
+57
View File
@@ -0,0 +1,57 @@
from click.testing import CliRunner
from mvt.ios.cli import check_sysdiagnose
CUSTOM_MODULE = """
from mvt.ios.modules.sysdiagnose import SysdiagnoseExtraction
class CustomSysdiagnoseModule(SysdiagnoseExtraction):
supported_commands = (("ios", "check-sysdiagnose"),)
slug = "custom_sysdiagnose_module"
def run(self):
file_path = self._get_files_by_pattern("*/artifact.txt")[0]
self.results = [{"content": self._get_file_content(file_path).decode("utf-8")}]
def check_indicators(self):
pass
def serialize(self, result):
return None
"""
def _create_sysdiagnose_folder(tmp_path):
folder = tmp_path / "sysdiagnose"
folder.mkdir()
(folder / "artifact.txt").write_text("artifact", encoding="utf-8")
return folder
def test_check_sysdiagnose_runs_explicitly_scoped_custom_module(tmp_path):
module_path = tmp_path / "custom_sysdiagnose.py"
module_path.write_text(CUSTOM_MODULE, encoding="utf-8")
output_path = tmp_path / "output"
result = CliRunner().invoke(
check_sysdiagnose,
[
"--load-module",
str(module_path),
"--output",
str(output_path),
str(_create_sysdiagnose_folder(tmp_path)),
],
)
assert result.exit_code == 0
assert (output_path / "custom_sysdiagnose_module.json").exists()
def test_check_sysdiagnose_requires_an_explicitly_scoped_module(tmp_path):
result = CliRunner().invoke(check_sysdiagnose, [str(_create_sysdiagnose_folder(tmp_path))])
assert result.exit_code != 0
assert "No custom modules support mvt-ios check-sysdiagnose" in result.output
+75
View File
@@ -0,0 +1,75 @@
import tarfile
from datetime import timedelta
from mvt.ios.cmd_check_sysdiagnose import CmdIOSCheckSysdiagnose
from mvt.ios.modules.sysdiagnose import SysdiagnoseExtraction
class SysdiagnoseTestModule(SysdiagnoseExtraction):
supported_commands = (("ios", "check-sysdiagnose"),)
def run(self):
file_path = self._get_files_by_pattern("*/artifact.txt")[0]
self.results = [
{
"content": self._get_file_content(file_path).decode("utf-8"),
"timezone_offset": self._extract_timezone().utcoffset(None).seconds,
}
]
def check_indicators(self):
pass
def serialize(self, result):
return None
def _create_sysdiagnose_folder(tmp_path):
folder = tmp_path / "sysdiagnose"
folder.mkdir()
(folder / "artifact.txt").write_text("artifact", encoding="utf-8")
(folder / "sysdiagnose.log").write_text(
"sysdiagnose_2024.01.02_03-04-05+0200.tar.gz", encoding="utf-8"
)
(folder / "report.ips").write_text('{"bug_type": 210}\nbody', encoding="utf-8")
return folder
def _create_sysdiagnose_archive(tmp_path, folder):
archive_path = tmp_path / "sysdiagnose.tar.gz"
with tarfile.open(archive_path, "w:gz") as archive:
for path in folder.iterdir():
archive.add(path, arcname=f"sysdiagnose/{path.name}")
return archive_path
def _run_command(path):
command = CmdIOSCheckSysdiagnose(
target_path=str(path), custom_modules=[SysdiagnoseTestModule]
)
command.run()
return command
def test_check_sysdiagnose_from_folder(tmp_path):
command = _run_command(_create_sysdiagnose_folder(tmp_path))
assert command.executed[0].results == [
{"content": "artifact", "timezone_offset": timedelta(hours=2).seconds}
]
assert command.executed[0].ips_files == [
{"file_path": str(tmp_path / "sysdiagnose" / "report.ips"), "bug_type": 210}
]
def test_check_sysdiagnose_from_archive_closes_archive(tmp_path):
folder = _create_sysdiagnose_folder(tmp_path)
command = _run_command(_create_sysdiagnose_archive(tmp_path, folder))
assert command.executed[0].results == [
{"content": "artifact", "timezone_offset": timedelta(hours=2).seconds}
]
assert command.executed[0].ips_files == [
{"file_path": "sysdiagnose/report.ips", "bug_type": 210}
]
assert command.sysdiagnose_archive is None