Commit initial

This commit is contained in:
2026-04-15 17:57:12 +02:00
parent 005d8e797e
commit 55516ee10f
269 changed files with 26854 additions and 0 deletions
+318
View File
@@ -0,0 +1,318 @@
"""
Unit tests for imptune.services.inf_parser.
Covers DRV-02 (INF parsing, token resolution, encoding detection,
multi-model) and DRV-05 (unused file detection).
"""
from pathlib import Path
import pytest
from imptune.services.inf_parser import ParsedInf, _detect_encoding, parse_inf
FIXTURES = Path(__file__).parent / "fixtures"
# ---------------------------------------------------------------------------
# _detect_encoding tests
# ---------------------------------------------------------------------------
def test_detect_encoding_utf16le():
"""UTF-16 LE BOM (\xff\xfe) is detected as 'utf-16'."""
raw = b"\xff\xfe" + "[Version]\r\n".encode("utf-16-le")
assert _detect_encoding(raw) == "utf-16"
def test_detect_encoding_utf16be():
"""UTF-16 BE BOM (\xfe\xff) is also detected as 'utf-16'."""
raw = b"\xfe\xff" + "[Version]\r\n".encode("utf-16-be")
assert _detect_encoding(raw) == "utf-16"
def test_detect_encoding_utf8bom():
"""UTF-8 BOM (\xef\xbb\xbf) is detected as 'utf-8-sig'."""
raw = b"\xef\xbb\xbf" + b"[Version]\r\n"
assert _detect_encoding(raw) == "utf-8-sig"
def test_detect_encoding_ansi():
"""Byte sequence with no BOM falls back to cp1252 (ANSI)."""
raw = b"[Version]\r\nSignature=\"$Windows NT$\"\r\n"
assert _detect_encoding(raw) == "cp1252"
# ---------------------------------------------------------------------------
# parse_inf simple INF with literal driver description
# ---------------------------------------------------------------------------
SIMPLE_INF = """
[Version]
Signature="$Windows NT$"
Class=Printer
[Manufacturer]
Acme=AcmeModels,NTamd64
[AcmeModels.NTamd64]
Acme SuperPrint 9000=Install,{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}
[Strings]
"""
def test_simple_driver_desc():
"""parse_inf extracts literal DriverDesc from a Models section."""
result = parse_inf(SIMPLE_INF, "acme.inf", ["acme.inf", "acme.dll"])
assert "Acme SuperPrint 9000" in result.driver_names
# ---------------------------------------------------------------------------
# parse_inf %TOKEN% resolution from [Strings]
# ---------------------------------------------------------------------------
TOKEN_INF = """
[Version]
Signature="$Windows NT$"
[Manufacturer]
%MFG%=Models,NTamd64
[Models.NTamd64]
%HP_DRIVER%=Install,{BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB}
[Strings]
MFG="HP"
HP_DRIVER="HP LaserJet"
"""
def test_token_resolution():
"""parse_inf resolves %TOKEN% references via the [Strings] section."""
result = parse_inf(TOKEN_INF, "hp.inf", ["hp.inf"])
assert "HP LaserJet" in result.driver_names
# Raw token should NOT appear in the output
assert "%HP_DRIVER%" not in result.driver_names
# ---------------------------------------------------------------------------
# parse_inf UTF-16 LE fixture
# ---------------------------------------------------------------------------
def test_utf16_encoding():
"""Reading a UTF-16 LE BOM fixture and passing decoded text to parse_inf produces correct driver_names."""
raw = (FIXTURES / "sample_utf16.inf").read_bytes()
encoding = _detect_encoding(raw)
assert encoding == "utf-16"
text = raw.decode(encoding, errors="replace")
result = parse_inf(text, "sample_utf16.inf", ["sample_utf16.inf"])
assert "Test LaserJet Pro" in result.driver_names
# ---------------------------------------------------------------------------
# parse_inf multi-model INF (NTamd64 + undecorated)
# ---------------------------------------------------------------------------
def test_multi_model_inf():
"""INF with both NTamd64 and undecorated sections returns deduplicated driver_names."""
text = (FIXTURES / "sample_multi_model.inf").read_text(encoding="cp1252")
result = parse_inf(text, "multi.inf", ["multi.inf"])
# Both driver names must appear exactly once
assert "Multi Printer 1000" in result.driver_names
assert "Multi Printer 2000" in result.driver_names
assert result.driver_names.count("Multi Printer 1000") == 1
assert result.driver_names.count("Multi Printer 2000") == 1
# ---------------------------------------------------------------------------
# parse_inf architecture detection
# ---------------------------------------------------------------------------
AMD64_INF = """
[Version]
Signature="$Windows NT$"
[Manufacturer]
Mfg=Mfg.Models,NTamd64
[Mfg.Models.NTamd64]
Some Driver=Install,{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}
[Strings]
"""
ARM64_INF = """
[Version]
Signature="$Windows NT$"
[Manufacturer]
Mfg=Mfg.Models,NTarm64
[Mfg.Models.NTarm64]
Some Driver=Install,{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}
[Strings]
"""
UNDECORATED_INF = """
[Version]
Signature="$Windows NT$"
[Manufacturer]
Mfg=Mfg.Models
[Mfg.Models]
Some Driver=Install,{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}
[Strings]
"""
MIXED_INF = """
[Version]
Signature="$Windows NT$"
[Manufacturer]
Mfg=Mfg.Models,Mfg.Models.NTamd64
[Mfg.Models]
Some Driver=Install,{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}
[Mfg.Models.NTamd64]
Some Driver=Install,{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}
[Strings]
"""
def test_architecture_detection_amd64():
"""NTamd64 decoration -> architecture='x64'."""
result = parse_inf(AMD64_INF, "amd64.inf", [])
assert result.architecture == "x64"
def test_architecture_detection_arm64():
"""NTarm64 decoration -> architecture='arm64'."""
result = parse_inf(ARM64_INF, "arm64.inf", [])
assert result.architecture == "arm64"
def test_architecture_detection_undecorated():
"""Undecorated section only -> architecture='x86'."""
result = parse_inf(UNDECORATED_INF, "x86.inf", [])
assert result.architecture == "x86"
def test_architecture_detection_mixed():
"""Mixed architectures -> architecture=None (ambiguous)."""
result = parse_inf(MIXED_INF, "mixed.inf", [])
assert result.architecture is None
# ---------------------------------------------------------------------------
# parse_inf .cat file detection
# ---------------------------------------------------------------------------
def test_cat_file_detection_present():
"""zip_names containing a .cat file -> has_cat_file=True."""
result = parse_inf(SIMPLE_INF, "acme.inf", ["acme.inf", "driver.cat", "acme.dll"])
assert result.has_cat_file is True
def test_cat_file_detection_absent():
"""zip_names without a .cat file -> has_cat_file=False."""
result = parse_inf(SIMPLE_INF, "acme.inf", ["acme.inf", "acme.dll"])
assert result.has_cat_file is False
# ---------------------------------------------------------------------------
# parse_inf unused files detection
# ---------------------------------------------------------------------------
def test_unused_files():
"""ZIP members not referenced in INF text appear in unused_files."""
inf_text = """
[Version]
Signature="$Windows NT$"
[Manufacturer]
Mfg=Mfg.Models
[Mfg.Models]
Some Driver=Install,{DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD}
[SourceDisksFiles]
driver.inf=1
driver.dll=1
[Strings]
"""
zip_names = ["driver.inf", "driver.dll", "readme.txt"]
result = parse_inf(inf_text, "driver.inf", zip_names)
# readme.txt is not mentioned anywhere in inf_text
assert "readme.txt" in result.unused_files
# driver.inf and driver.dll ARE referenced in inf_text
assert "driver.inf" not in result.unused_files
assert "driver.dll" not in result.unused_files
# ---------------------------------------------------------------------------
# parse_inf empty models section
# ---------------------------------------------------------------------------
EMPTY_MODELS_INF = """
[Version]
Signature="$Windows NT$"
[Manufacturer]
Mfg=MfgModels
[MfgModels]
[Strings]
"""
def test_empty_models_section():
"""INF with empty Models section returns empty driver_names list."""
result = parse_inf(EMPTY_MODELS_INF, "empty.inf", [])
assert result.driver_names == []
# ---------------------------------------------------------------------------
# parse_inf tolerates bare-line sections (real-world Ricoh oemsetup.inf)
# ---------------------------------------------------------------------------
BARE_LINE_INF = """\
[Version]
Signature="$Windows NT$"
[Manufacturer]
%MFG%=Models,NTamd64
[Models.NTamd64]
%RICOH_DRIVER%=Install,{CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC}
[SourceDisksFiles]
ricu18ui.dll,ricu18ui.dl_
ricu18ui.irj
ricu18ui.rdj
ricu18gl.dll,ricu18gl.dl_
RD01Kd64.dll,RD01Kd64.dl_,,0x00000020
[Strings]
MFG="Ricoh"
RICOH_DRIVER="Ricoh PCL6 Universal"
"""
def test_bare_line_sections_do_not_raise():
"""Real INFs (e.g. Ricoh oemsetup.inf) include [SourceDisksFiles] entries
with bare filename lines and no '=' — parse_inf must not raise and must
still extract DriverDesc from the Models section."""
result = parse_inf(BARE_LINE_INF, "oemsetup.inf", ["oemsetup.inf"])
assert "Ricoh PCL6 Universal" in result.driver_names
# Synthetic __bare_N keys must not leak into driver_names
assert not any(n.startswith("__bare_") for n in result.driver_names)