Merge pull request #115 from trustedsec/fix/pcfg-test-isolation

test: fix hate_path leak causing flaky test_main_pcfg
This commit is contained in:
Justin Bollinger
2026-07-27 13:49:52 -04:00
committed by GitHub
2 changed files with 26 additions and 10 deletions
+10
View File
@@ -17,6 +17,15 @@ class TestHcatPCFG:
hash_file = str(tmp_path / "hashes.txt")
Path(hash_file).write_text("dummy")
# hcatPCFG resolves pcfg_guesser.py under the module global hate_path
# and bails early if it's missing. Pin hate_path to a tmp dir with a
# stub script so the test is hermetic — independent of the real
# pcfg_cracker submodule being checked out and of any hate_path value
# leaked by an earlier test (hate_crack.main is shared session-wide).
pcfg_dir = tmp_path / "pcfg_cracker"
pcfg_dir.mkdir()
(pcfg_dir / "pcfg_guesser.py").write_text("# stub")
captured_calls = []
class FakeProc:
@@ -27,6 +36,7 @@ class TestHcatPCFG:
with patch("hate_crack.main.subprocess.Popen", side_effect=FakeProc), \
patch("hate_crack.main._run_hcat_cmd") as mock_run, \
patch.object(main_module, "hate_path", str(tmp_path)), \
patch.object(main_module, "hcatBin", "hashcat"), \
patch.object(main_module, "hcatTuning", ""), \
patch.object(main_module, "hcatPotfilePath", ""), \
+16 -10
View File
@@ -10,14 +10,18 @@ import pytest
class TestMarkovE2E:
"""End-to-end tests for complete markov attack workflow."""
def test_markov_training_plain_text(self, tmp_path: Path) -> None:
def test_markov_training_plain_text(self, tmp_path: Path, monkeypatch) -> None:
"""Test markov training with plain text wordlist."""
from hate_crack import main
# Setup paths
main.hate_path = Path(__file__).resolve().parents[1]
main.hcatHcstat2genBin = "hcstat2gen.bin"
bin_path = main.hate_path / "hashcat-utils" / "bin" / "hcstat2gen.bin"
# Setup paths. Use monkeypatch so these module globals are restored
# after the test — hate_crack.main is imported once and shared across
# the whole session, so a raw assignment here would leak into every
# later test (e.g. test_main_pcfg, which reads the ambient hate_path).
repo_root = Path(__file__).resolve().parents[1]
monkeypatch.setattr(main, "hate_path", repo_root)
monkeypatch.setattr(main, "hcatHcstat2genBin", "hcstat2gen.bin")
bin_path = repo_root / "hashcat-utils" / "bin" / "hcstat2gen.bin"
if not bin_path.is_file():
pytest.skip(f"hcstat2gen.bin not compiled: {bin_path}")
@@ -39,14 +43,16 @@ class TestMarkovE2E:
assert hcstat2_path.exists(), ".hcstat2 file should be created"
assert hcstat2_path.stat().st_size > 0, ".hcstat2 file should not be empty"
def test_markov_training_gzipped(self, tmp_path: Path) -> None:
def test_markov_training_gzipped(self, tmp_path: Path, monkeypatch) -> None:
"""Test markov training with gzipped wordlist."""
from hate_crack import main
# Setup paths
main.hate_path = Path(__file__).resolve().parents[1]
main.hcatHcstat2genBin = "hcstat2gen.bin"
bin_path = main.hate_path / "hashcat-utils" / "bin" / "hcstat2gen.bin"
# Setup paths (monkeypatch so these session-shared module globals are
# restored after the test — see test_markov_training_plain_text).
repo_root = Path(__file__).resolve().parents[1]
monkeypatch.setattr(main, "hate_path", repo_root)
monkeypatch.setattr(main, "hcatHcstat2genBin", "hcstat2gen.bin")
bin_path = repo_root / "hashcat-utils" / "bin" / "hcstat2gen.bin"
if not bin_path.is_file():
pytest.skip(f"hcstat2gen.bin not compiled: {bin_path}")