mirror of
https://github.com/trustedsec/hate_crack.git
synced 2026-03-12 21:23:05 -07:00
- Fix line length and formatting in hate_crack/api.py - Fix line wrapping and f-string formatting in hate_crack/attacks.py - Apply code style improvements in hate_crack/main.py - Format test files for consistency - All changes applied via 'ruff check --fix'
206 lines
5.9 KiB
Python
206 lines
5.9 KiB
Python
import logging
|
|
import os
|
|
import importlib
|
|
|
|
|
|
from hate_crack import api
|
|
from hate_crack import cli
|
|
from hate_crack import formatting
|
|
|
|
|
|
def test_resolve_path_none_and_expand():
|
|
assert cli.resolve_path("") is None
|
|
resolved = cli.resolve_path("~")
|
|
assert resolved is not None
|
|
assert os.path.isabs(resolved)
|
|
|
|
|
|
def test_setup_logging_adds_single_streamhandler(tmp_path):
|
|
logger = logging.getLogger("hate_crack_test")
|
|
logger.handlers.clear()
|
|
cli.setup_logging(logger, str(tmp_path), debug_mode=True)
|
|
cli.setup_logging(logger, str(tmp_path), debug_mode=True)
|
|
|
|
stream_handlers = [
|
|
h
|
|
for h in logger.handlers
|
|
if isinstance(h, logging.StreamHandler)
|
|
and not isinstance(h, logging.FileHandler)
|
|
]
|
|
assert len(stream_handlers) == 1
|
|
file_handlers = [h for h in logger.handlers if isinstance(h, logging.FileHandler)]
|
|
assert file_handlers == []
|
|
|
|
logger.handlers.clear()
|
|
|
|
|
|
def test_print_multicolumn_list_truncates(capsys, monkeypatch):
|
|
# Avoid patching os.get_terminal_size (pytest uses it internally).
|
|
monkeypatch.setattr(formatting, "_terminal_width", lambda default=120: 10)
|
|
formatting.print_multicolumn_list(
|
|
"Title",
|
|
["abcdefghijk"],
|
|
min_col_width=1,
|
|
max_col_width=10,
|
|
)
|
|
captured = capsys.readouterr()
|
|
assert "..." in captured.out
|
|
|
|
|
|
def test_print_multicolumn_list_empty_entries(capsys):
|
|
formatting.print_multicolumn_list("Empty", [])
|
|
captured = capsys.readouterr()
|
|
assert "(none)" in captured.out
|
|
|
|
|
|
def test_get_hcat_wordlists_dir_from_config(tmp_path, monkeypatch):
|
|
config_path = tmp_path / "config.json"
|
|
config_path.write_text('{"hcatWordlists": "wordlists"}')
|
|
|
|
monkeypatch.setattr(api, "_resolve_config_path", lambda: str(config_path))
|
|
result = api.get_hcat_wordlists_dir()
|
|
|
|
assert result == str(tmp_path / "wordlists")
|
|
assert os.path.isdir(result)
|
|
|
|
|
|
def test_get_hcat_wordlists_dir_fallback_cwd(tmp_path, monkeypatch):
|
|
monkeypatch.setattr(api, "_resolve_config_path", lambda: None)
|
|
monkeypatch.chdir(tmp_path)
|
|
|
|
result = api.get_hcat_wordlists_dir()
|
|
|
|
assert result == str(tmp_path / "wordlists")
|
|
assert os.path.isdir(result)
|
|
|
|
|
|
def test_get_rules_dir_from_config(tmp_path, monkeypatch):
|
|
config_path = tmp_path / "config.json"
|
|
config_path.write_text('{"rules_directory": "rules"}')
|
|
|
|
monkeypatch.setattr(api, "_resolve_config_path", lambda: str(config_path))
|
|
result = api.get_rules_dir()
|
|
|
|
assert result == str(tmp_path / "rules")
|
|
assert os.path.isdir(result)
|
|
|
|
|
|
def test_get_rules_dir_fallback_cwd(tmp_path, monkeypatch):
|
|
monkeypatch.setattr(api, "_resolve_config_path", lambda: None)
|
|
monkeypatch.chdir(tmp_path)
|
|
|
|
result = api.get_rules_dir()
|
|
|
|
assert result == str(tmp_path / "rules")
|
|
assert os.path.isdir(result)
|
|
|
|
|
|
def test_cleanup_torrent_files_removes_only_torrents(tmp_path):
|
|
torrent = tmp_path / "a.torrent"
|
|
keep = tmp_path / "b.txt"
|
|
torrent.write_text("data")
|
|
keep.write_text("data")
|
|
|
|
api.cleanup_torrent_files(directory=str(tmp_path))
|
|
|
|
assert not torrent.exists()
|
|
assert keep.exists()
|
|
|
|
|
|
def test_cleanup_torrent_files_missing_dir(capsys, tmp_path):
|
|
missing = tmp_path / "missing"
|
|
api.cleanup_torrent_files(directory=str(missing))
|
|
captured = capsys.readouterr()
|
|
assert "Failed to cleanup torrent files" in captured.out
|
|
|
|
|
|
def test_register_torrent_cleanup_idempotent(monkeypatch):
|
|
calls = []
|
|
|
|
def fake_register(fn):
|
|
calls.append(fn)
|
|
|
|
monkeypatch.setattr(api, "_TORRENT_CLEANUP_REGISTERED", False)
|
|
monkeypatch.setattr("atexit.register", fake_register)
|
|
|
|
api.register_torrent_cleanup()
|
|
api.register_torrent_cleanup()
|
|
|
|
assert len(calls) == 1
|
|
|
|
|
|
def test_line_count_and_write_helpers(tmp_path, monkeypatch):
|
|
monkeypatch.setenv("HATE_CRACK_SKIP_INIT", "1")
|
|
from hate_crack import main as main_module
|
|
|
|
importlib.reload(main_module)
|
|
|
|
input_path = tmp_path / "input.txt"
|
|
input_path.write_text("a:b:c\nno-delim\n1:2:3\n")
|
|
out_delimited = tmp_path / "out_delimited.txt"
|
|
out_unique = tmp_path / "out_unique.txt"
|
|
|
|
assert main_module.lineCount(str(input_path)) == 3
|
|
assert main_module.lineCount(str(tmp_path / "missing.txt")) == 0
|
|
|
|
assert (
|
|
main_module._write_delimited_field(str(input_path), str(out_delimited), 2)
|
|
is True
|
|
)
|
|
assert out_delimited.read_text().splitlines() == ["b", "2"]
|
|
assert (
|
|
main_module._write_delimited_field(
|
|
str(tmp_path / "missing.txt"), str(out_delimited), 2
|
|
)
|
|
is False
|
|
)
|
|
|
|
class FakePopen:
|
|
def __init__(self, args, stdin=None, stdout=None, text=None):
|
|
self.stdin = FakeStdin(self)
|
|
self._stdout = stdout
|
|
self._data = None
|
|
|
|
def wait(self):
|
|
for line in sorted(set(self._data)):
|
|
self._stdout.write(line + "\n")
|
|
return 0
|
|
|
|
class FakeStdin:
|
|
def __init__(self, popen):
|
|
self._popen = popen
|
|
self._lines = []
|
|
|
|
def write(self, data):
|
|
self._lines.append(data.rstrip("\n"))
|
|
|
|
def close(self):
|
|
self._popen._data = self._lines
|
|
|
|
monkeypatch.setattr(main_module.subprocess, "Popen", FakePopen)
|
|
|
|
assert (
|
|
main_module._write_field_sorted_unique(str(input_path), str(out_unique), 2)
|
|
is True
|
|
)
|
|
assert out_unique.read_text().splitlines() == ["2", "b"]
|
|
|
|
|
|
def test_get_customer_hashfiles_with_hashtype_filters(monkeypatch):
|
|
hv = api.HashviewAPI("https://example", "key")
|
|
monkeypatch.setattr(
|
|
hv,
|
|
"get_customer_hashfiles",
|
|
lambda customer_id: [
|
|
{"customer_id": customer_id, "hashtype": "1000"},
|
|
{"customer_id": customer_id, "hash_type": "0"},
|
|
],
|
|
)
|
|
|
|
matches = hv.get_customer_hashfiles_with_hashtype(1, target_hashtype="1000")
|
|
assert len(matches) == 1
|
|
assert matches[0]["hashtype"] == "1000"
|
|
|
|
none = hv.get_customer_hashfiles_with_hashtype(1, target_hashtype="999")
|
|
assert none == []
|