Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
24 changes: 24 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import ast
import importlib.util
import pathlib
import tempfile
Expand Down Expand Up @@ -80,6 +81,29 @@ def pytest_sessionstart(session: pytest.Session) -> None:
)
break

function_names = {}
Comment thread
JSCU-CNI marked this conversation as resolved.
Outdated


@pytest.hookimpl(tryfirst=True)
def pytest_pycollect_makemodule(module_path: str, parent: str) -> None:
if duplicates := find_duplicate_functions(module_path):
pytest.exit(f"duplicate functions found in module: {module_path}: {duplicates}")
Comment thread
JSCU-CNI marked this conversation as resolved.
Outdated


def find_duplicate_functions(source_path: str) -> set[str]:
source_code = pathlib.Path(source_path).read_text()
tree = ast.parse(source_code, source_path)
duplicates = set()
allowlist = ("test_other", "test_all", "test_target_open", "test_loader")
Comment thread
JSCU-CNI marked this conversation as resolved.
Outdated

for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef) and node.name.startswith("test_") and node.name not in allowlist:
if node.name in function_names:
duplicates.add(node.name)
else:
function_names[node.name] = node
return duplicates


def pytest_runtest_setup(item: pytest.Item) -> None:
if not HAS_BENCHMARK and item.get_closest_marker("benchmark") is not None:
Expand Down
2 changes: 1 addition & 1 deletion tests/filesystems/test_extfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from tests._utils import absolute_path


def test_stat_information() -> None:
def test_extfs_stat_information() -> None:
extfs = Mock(block_size=0x1000)
extfs.sb.s_inode_size = 129

Expand Down
2 changes: 1 addition & 1 deletion tests/filesystems/test_ffs.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def ffs_fs_entry(ffs_fs: FfsFilesystem) -> FfsFilesystemEntry:
return FfsFilesystemEntry(ffs_fs, "/some_file", inode)


def test_jffs2_stat(ffs_fs_entry: FfsFilesystemEntry) -> None:
def test_ffs_stat(ffs_fs_entry: FfsFilesystemEntry) -> None:
stat = ffs_fs_entry.stat()

entry = ffs_fs_entry.entry
Expand Down
2 changes: 1 addition & 1 deletion tests/filesystems/test_nfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def test_is_symlink(nfs_filesystem_entry: NfsFilesystemEntry) -> None:
assert nfs_filesystem_entry.is_symlink()


def test_readlink(nfs_filesystem_entry: NfsFilesystemEntry, mock_nfs_client: MagicMock) -> None:
def test_nfs_readlink(nfs_filesystem_entry: NfsFilesystemEntry, mock_nfs_client: MagicMock) -> None:
mock_nfs_client.readlink.return_value = "/target"
target = nfs_filesystem_entry.readlink()
mock_nfs_client.readlink.assert_called_with(FileHandle(opaque=b"file_handle"))
Expand Down
2 changes: 1 addition & 1 deletion tests/filesystems/test_ntfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_ntfs_unknown_file() -> None:
(0x1000, 0x2000, True, 0),
],
)
def test_stat_information(cluster_size: int, size: int, resident: bool, expected_blks: int) -> None:
def test_ntfs_stat_information(cluster_size: int, size: int, resident: bool, expected_blks: int) -> None:
ntfs = Mock(cluster_size=cluster_size)

entry = MftRecord()
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers/sunrpc/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def test_getattr(mock_socket: MagicMock) -> None:
)


def test_readlink(mock_socket: MagicMock) -> None:
def test_sunrpc_readlink(mock_socket: MagicMock) -> None:
readlink_request = b"\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xa3\x00\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x1ccy7\xba\x00\x00\x00\x07machine\x00\x00\x00\x03\xe8\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\x01\x00\x07\x02\xda&\xee\x02\x00\x00\x00\x00\xb5g\x131&\xf1I\xed\xb8R\rx\\h8\xb4\x0f{\xee\x02\xefoz\xef\xda&\xee\x02'/\x00\x91" # noqa: E501
readlink_response = b"\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x01\xff\x00\x00\x00\x01\x00\x00\x03\xe8\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Yq\x99zI\x1e5\r\x00\x00\x00\x00\x02\xee{\x0fg\xac\xba\xc3\r5\xab\xa0g\xa9\xbe\x0c:H\x15\xc0g\xa9\xbe\x0c:H\x15\xc0\x00\x00\x00\x0edir1/dir2/dir3\x00\x00" # noqa: E501

Expand Down
24 changes: 16 additions & 8 deletions tests/helpers/test_configutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,30 +84,33 @@ def test_custom_comments(comment_string: str, comment_prefixes: tuple[str, ...])
@pytest.mark.parametrize(
("indented_string", "expected_output"),
[
(
pytest.param(
"""
key value1
value2
""",
{"key value1": "value2"},
id="variant-1",
),
(
pytest.param(
"""
key1 value1
key2 value2
""",
{"key1 value1": {"key2": "value2"}},
id="variant-2",
),
(
pytest.param(
"""
key value1
value2
key value1
value3
""",
{"key value1": ["value2", "value3"]},
id="variant-3",
),
(
pytest.param(
"""
key value1
key2 value2a
Expand All @@ -117,8 +120,9 @@ def test_custom_comments(comment_string: str, comment_prefixes: tuple[str, ...])
key3 value3b
""",
{"key value1": [{"key2": "value2a", "key3": "value3a"}, {"key2": "value2b", "key3": "value3b"}]},
id="variant-4",
),
(
pytest.param(
"""
key value
key2 value2
Expand All @@ -128,8 +132,9 @@ def test_custom_comments(comment_string: str, comment_prefixes: tuple[str, ...])
key2 value2
""",
{"key value": {"key2": "value2", "key3": "value3"}, "key value4": {"key2": "value2"}},
id="variant-5",
),
(
pytest.param(
"""
key value
key2 value2
Expand All @@ -139,15 +144,17 @@ def test_custom_comments(comment_string: str, comment_prefixes: tuple[str, ...])
key2
""",
{"key value": {"key2": "value2", "key3": "value3"}, "key value4": "key2"},
id="variant-6",
),
(
pytest.param(
"""
key value
value2
key2 value
key3 value3
""",
{"key value": "value2", "key2 value": {"key3": "value3"}},
id="variant-6",
),
],
)
Expand Down Expand Up @@ -383,7 +390,7 @@ def test_env_parser(input: str | Path, expected_output: dict) -> None:
@pytest.mark.parametrize(
("string_data", "expected_output"),
[
(
pytest.param(
'default-duid "\\000\\001\\000\\001\\037\\305\\371\\341\\001\\002\\003\\004\\005\\006"\nlease {\ninterface "eth0"; # some comment\nfixed-address "1.2.3.4";\noption subnet-mask 255.255.255.0;\nrenew 2 2023/10/04 13:37:04;\n# some other comment}', # noqa: E501
{
"default-duid": '"\\000\\001\\000\\001\\037\\305\\371\\341\\001\\002\\003\\004\\005\\006"',
Expand All @@ -394,6 +401,7 @@ def test_env_parser(input: str | Path, expected_output: dict) -> None:
"renew": "2 2023/10/04 13:37:04",
},
},
id="dhcp-lease",
),
],
)
Expand Down
2 changes: 1 addition & 1 deletion tests/helpers/test_fsutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,7 @@ def glob_fs() -> VirtualFilesystem:
("/", "boo/bla/*", []),
],
)
def test_glob_ext(glob_fs: VirtualFilesystem, start_path: str, pattern: str, results: list[str]) -> None:
def test_fsutil_glob_ext(glob_fs: VirtualFilesystem, start_path: str, pattern: str, results: list[str]) -> None:
start_entry = glob_fs.get(start_path)
entries = fsutil.glob_ext(start_entry, pattern)

Expand Down
11 changes: 9 additions & 2 deletions tests/helpers/test_magic.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,19 @@
("from_buffer", b"\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1", True, "application/vnd.ms-excel"),
("from_buffer", b"Received:", True, "message/rfc822"),
("from_buffer", b"!BDN", True, "application/vnd.ms-outlook-pst"),
("from_buffer", (b"\x00" * 2112) + b"Microsoft Word document data", True, "application/msword"),
(
pytest.param(
"from_buffer",
(b"\x00" * 2112) + b"Microsoft Word document data",
True,
"application/msword",
id="msword",
Comment thread
JSCU-CNI marked this conversation as resolved.
),
pytest.param(
"from_buffer",
(b"\x00" * 592) + bytes.fromhex("108d81649b4fcf1186ea00aa00b929e8"),
True,
"application/vnd.ms-powerpoint",
id="mspowerpoint",
),
# Executables
("from_buffer", b"MZ", True, "application/x-ms-dos-executable"),
Expand Down
12 changes: 10 additions & 2 deletions tests/helpers/test_protobuf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,16 @@ def test_protobuf_varint_decode(input: bytes, expected_output: int) -> None:
@pytest.mark.parametrize(
("input", "expected_output"),
[
(1234567890, b"\xd2\x85\xd8\xcc\x04"),
(pow(2, 128), b"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x04"),
pytest.param(
1234567890,
b"\xd2\x85\xd8\xcc\x04",
id="1234567890",
),
pytest.param(
pow(2, 128),
b"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x04",
id="pow(2, 128)",
),
],
)
def test_protobuf_varint_encode(input: int, expected_output: bytes) -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/loaders/test_acquire.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def test_anonymous_filesystems() -> None:
],
)
@pytest.mark.benchmark
def test_benchmark(benchmark: BenchmarkFixture, archive: str, loader: type[Loader]) -> None:
def test_benchmark_acquire(benchmark: BenchmarkFixture, archive: str, loader: type[Loader]) -> None:
"""Benchmark the loading of Acquire archives."""
file = absolute_path(archive)

Expand Down
4 changes: 2 additions & 2 deletions tests/loaders/test_containerimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_target_open(opener: Callable[[str | Path], Target]) -> None:
assert target.path == path


def test_docker() -> None:
def test_containerimage_docker() -> None:
"""Test if we map a Docker image correctly."""
path = absolute_path("_data/loaders/containerimage/alpine-docker.tar")

Expand Down Expand Up @@ -75,7 +75,7 @@ def test_docker() -> None:
]


def test_oci_podman() -> None:
def test_containerimage_oci_podman() -> None:
"""Test if we map a Podman OCI image correctly."""
path = absolute_path("_data/loaders/containerimage/alpine-oci.tar")

Expand Down
2 changes: 1 addition & 1 deletion tests/loaders/test_kape.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def test_target_open(opener: Callable[[str | Path], Target], mock_kape_dir: Path


@patch("dissect.target.filesystems.dir.DirectoryFilesystem.ntfs", None, create=True)
def test_dir(mock_kape_dir: Path) -> None:
def test_dir_kape(mock_kape_dir: Path) -> None:
Comment thread
JSCU-CNI marked this conversation as resolved.
Outdated
"""Test the ``KapeLoader`` with a directory."""
loader = loader_open(mock_kape_dir)
assert isinstance(loader, KapeLoader)
Expand Down
2 changes: 1 addition & 1 deletion tests/loaders/test_nscollector.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_target_open(opener: Callable[[str | Path], Target]) -> None:
assert target.path == path


def test_compressed_tar(caplog: pytest.LogCaptureFixture) -> None:
def test_ns_compressed_tar(caplog: pytest.LogCaptureFixture) -> None:
"""Test if we map a compressed NetScaler Collector tar image correctly."""
path = absolute_path("_data/loaders/nscollector/collector_P_10.164.0.3_22Oct2025_11_31.tar.gz")

Expand Down
2 changes: 1 addition & 1 deletion tests/loaders/test_overlay2.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_target_open(opener: Callable[[str | Path], Target], target_linux_docker
("f988f88e221d97930a665712cf16ab520f7e2c5af395660c145df93aebedf071", 9, 19),
],
)
def test_docker(target_linux_docker: Target, path: str, layers: int, entries: int) -> None:
def test_overlay2_docker(target_linux_docker: Target, path: str, layers: int, entries: int) -> None:
"""Test if we correctly detect and map a Docker container."""
container = target_linux_docker.fs.path("/var/lib/docker/image/overlay2/layerdb/mounts").joinpath(path)

Expand Down
6 changes: 3 additions & 3 deletions tests/loaders/test_uac.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def test_target_open(
("_data/loaders/uac/uac-2e44ea6da71d-linux-20250717143112.tar.gz"),
],
)
def test_compressed_tar(data_path: str) -> None:
def test_uac_compressed_tar(data_path: str) -> None:
"""Test if we map a compressed UAC tar image correctly."""
path = absolute_path(data_path)

Expand Down Expand Up @@ -109,7 +109,7 @@ def test_compressed_zip() -> None:
assert test_file.open().readline() == b"root:x:0:0:root:/root:/bin/bash\n"


def test_dir(mock_uac_dir: Path) -> None:
def test_dir_uac(mock_uac_dir: Path) -> None:
Comment thread
JSCU-CNI marked this conversation as resolved.
Outdated
"""Test if we map an extracted UAC directory correctly."""
loader = loader_open(mock_uac_dir)
assert isinstance(loader, UacLoader)
Expand All @@ -133,7 +133,7 @@ def test_dir(mock_uac_dir: Path) -> None:
],
)
@pytest.mark.benchmark
def test_benchmark(benchmark: BenchmarkFixture, archive: str, loader: type[Loader]) -> None:
def test_benchmark_uac(benchmark: BenchmarkFixture, archive: str, loader: type[Loader]) -> None:
file = absolute_path(archive)

benchmark(lambda: loader(file).map(Target()))
2 changes: 1 addition & 1 deletion tests/loaders/test_velociraptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def test_windows_ntfs_zip(mock_velociraptor_dir: Path) -> None:
(["uploads/auto/Library", "uploads/auto/Applications", "uploads/auto/%2ETEST"]),
],
)
def test_unix(paths: list[str], tmp_path: Path) -> None:
def test_velo_unix(paths: list[str], tmp_path: Path) -> None:
"""Test that ``VelociraptorLoader`` correctly loads a Unix directory structure."""
root = tmp_path
mkdirs(root, paths)
Expand Down
6 changes: 3 additions & 3 deletions tests/loaders/test_vmsupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def test_target_open(
"_data/loaders/vmsupport/esx-localhost8-2026-01-09--16.04-135806.tgz",
],
)
def test_compressed_tar(data_path: str) -> None:
def test_vmsupport_compressed_tar(data_path: str) -> None:
"""Test if we map a compressed vm support tar image correctly."""
path = absolute_path(data_path)

Expand All @@ -88,7 +88,7 @@ def test_compressed_tar(data_path: str) -> None:
assert b"/resourceGroups/version" in test_file.open().read()


def test_dir(mock_vmsupport_dir: Path) -> None:
def test_dir_vmsupport(mock_vmsupport_dir: Path) -> None:
Comment thread
JSCU-CNI marked this conversation as resolved.
Outdated
"""Test if we map an extracted vm support directory correctly."""
loader = loader_open(mock_vmsupport_dir)
assert isinstance(loader, VmSupportLoader)
Expand All @@ -112,7 +112,7 @@ def test_dir(mock_vmsupport_dir: Path) -> None:
],
)
@pytest.mark.benchmark
def test_benchmark(benchmark: BenchmarkFixture, archive: str, loader: type[Loader]) -> None:
def test_benchmark_vmsupport(benchmark: BenchmarkFixture, archive: str, loader: type[Loader]) -> None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't test_vmsupport_benchmark be more consistent? Also goes for the other benchmarks.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under the impression test_benchmark_* was the standard prefix for benchmark tests.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me too 😄 idk man. Keep these as-is then. Maybe worth adding a check that @pytest.mark.benchmark marked tests start with test_benchmark_.

file = absolute_path(archive)

benchmark(lambda: loader(file).map(Target()))
6 changes: 4 additions & 2 deletions tests/plugins/apps/browser/test_firefox.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,15 @@ def target_firefox_oculus(target_android: Target, fs_android: VirtualFilesystem)
@pytest.mark.parametrize(
("target_platform", "expected_source"),
[
(
pytest.param(
"target_firefox_win",
"C:\\Users\\John\\AppData\\local\\Mozilla\\Firefox\\Profiles\\g1rbw8y7.default-release\\places.sqlite",
id="windows",
),
(
pytest.param(
"target_firefox_unix",
"/root/.mozilla/firefox/g1rbw8y7.default-release/places.sqlite",
id="unix",
),
],
)
Expand Down
10 changes: 8 additions & 2 deletions tests/plugins/apps/shell/test_powershell.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@
@pytest.mark.parametrize(
("target", "fs", "target_file"),
[
(
pytest.param(
"target_win_users",
"fs_win",
"users\\John\\AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\psreadline\\ConsoleHost_history.txt",
id="windows",
),
pytest.param(
"target_unix_users",
"fs_unix",
"/root/.local/share/powershell/PSReadLine/ConsoleHost_history.txt",
id="unix",
),
("target_unix_users", "fs_unix", "/root/.local/share/powershell/PSReadLine/ConsoleHost_history.txt"),
],
)
def test_powershell(target: str, fs: str, target_file: str, request: pytest.FixtureRequest) -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/plugins/child/test_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from dissect.target.target import Target


def test_docker(target_linux_docker: Target) -> None:
def test_docker_child(target_linux_docker: Target) -> None:
target_linux_docker.add_plugin(DockerChildTargetPlugin)
children = sorted([child for _, child in target_linux_docker.list_children()], key=lambda r: r.path)

Expand Down
Loading