🧪 Add test file for cli.py (#21)

* Add initial test suite for cli.py

Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com>

* drop redundant pytest-cov dep addition

---------

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
Horizontal42 2026-08-19 17:36:36 +03:00 • committed by GitHub
parent 5b771739e6
commit 45ce7509d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,62 +1,110 @@
import os import os
from pathlib import Path
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from netsleuth.cli import _os_timezone from netsleuth.cli import _dedupe, _os_timezone, parse_target
from netsleuth.models import Finding
def test_os_timezone_tz_env(): def test_parse_target_asn():
with patch.dict(os.environ, {"TZ": "Europe/Berlin"}): assert parse_target("AS12345") == ("asn", "AS12345")
assert _os_timezone() == "Europe/Berlin" assert parse_target("as12345") == ("asn", "AS12345")
assert parse_target("12345") == ("asn", "AS12345")
assert parse_target(" AS12345 ") == ("asn", "AS12345")
def test_os_timezone_localtime_symlink():
with patch.dict(os.environ, {}, clear=True):
with patch("netsleuth.cli.Path") as MockPath:
mock_localtime = MagicMock()
mock_localtime.is_symlink.return_value = True
mock_localtime.readlink.return_value = "/usr/share/zoneinfo/America/New_York"
# Make Path("/etc/localtime") return mock_localtime def test_parse_target_ip():
MockPath.return_value = mock_localtime assert parse_target("1.2.3.4") == ("ip", "1.2.3.4")
assert parse_target("2001:db8::1") == ("ip", "2001:db8::1")
assert parse_target(" 1.2.3.4 ") == ("ip", "1.2.3.4")
assert _os_timezone() == "America/New_York"
MockPath.assert_called_once_with("/etc/localtime")
def test_os_timezone_timezone_file(): def test_parse_target_domain():
with patch.dict(os.environ, {}, clear=True): assert parse_target("example.com") == ("domain", "example.com")
with patch("netsleuth.cli.Path") as MockPath: assert parse_target("foo-bar.baz") == ("domain", "foo-bar.baz")
mock_localtime = MagicMock() assert parse_target(" example.com ") == ("domain", "example.com")
mock_localtime.is_symlink.return_value = False
mock_timezone = MagicMock()
mock_timezone.read_text.return_value = "Asia/Tokyo\n"
def side_effect(path): def test_dedupe_empty():
if path == "/etc/localtime": assert _dedupe([]) == []
return mock_localtime
elif path == "/etc/timezone":
return mock_timezone
return MagicMock()
MockPath.side_effect = side_effect
assert _os_timezone() == "Asia/Tokyo" def test_dedupe_unique():
findings = [
Finding(id="f1", severity="info", title="1", detail="1"),
Finding(id="f2", severity="info", title="2", detail="2"),
Finding(id="f3", severity="info", title="3", detail="3"),
]
assert _dedupe(findings) == findings
def test_os_timezone_oserror():
with patch.dict(os.environ, {}, clear=True):
with patch("netsleuth.cli.Path") as MockPath:
mock_localtime = MagicMock()
mock_localtime.is_symlink.return_value = False
mock_timezone = MagicMock() def test_dedupe_duplicates():
mock_timezone.read_text.side_effect = OSError("Permission denied") f1 = Finding(id="f1", severity="info", title="1", detail="1")
f2 = Finding(id="f2", severity="info", title="2", detail="2")
f1_dup = Finding(id="f1", severity="warn", title="dup", detail="dup")
findings = [f1, f2, f1_dup, f1, f2]
deduped = _dedupe(findings)
assert len(deduped) == 2
assert deduped[0] is f1
assert deduped[1] is f2
def side_effect(path):
if path == "/etc/localtime":
return mock_localtime
elif path == "/etc/timezone":
return mock_timezone
return MagicMock()
MockPath.side_effect = side_effect def test_os_timezone_from_env(monkeypatch):
monkeypatch.setenv("TZ", "America/New_York")
assert _os_timezone() == "America/New_York"
assert _os_timezone() is None
@patch("netsleuth.cli.Path")
def test_os_timezone_from_localtime_symlink(mock_path, monkeypatch):
monkeypatch.delenv("TZ", raising=False)
mock_localtime = MagicMock()
mock_localtime.is_symlink.return_value = True
mock_localtime.readlink.return_value = Path("/usr/share/zoneinfo/Europe/London")
def side_effect(path, *args, **kwargs):
if str(path) == "/etc/localtime":
return mock_localtime
return MagicMock()
mock_path.side_effect = side_effect
assert _os_timezone() == "Europe/London"
@patch("netsleuth.cli.Path")
def test_os_timezone_from_timezone_file(mock_path, monkeypatch):
monkeypatch.delenv("TZ", raising=False)
mock_localtime = MagicMock()
mock_localtime.is_symlink.return_value = False
mock_timezone = MagicMock()
mock_timezone.read_text.return_value = "Asia/Tokyo\n"
def side_effect(path, *args, **kwargs):
if str(path) == "/etc/localtime":
return mock_localtime
if str(path) == "/etc/timezone":
return mock_timezone
return MagicMock()
mock_path.side_effect = side_effect
assert _os_timezone() == "Asia/Tokyo"
@patch("netsleuth.cli.Path")
def test_os_timezone_none(mock_path, monkeypatch):
monkeypatch.delenv("TZ", raising=False)
mock_localtime = MagicMock()
mock_localtime.is_symlink.return_value = False
mock_timezone = MagicMock()
mock_timezone.read_text.side_effect = OSError("File not found")
def side_effect(path, *args, **kwargs):
if str(path) == "/etc/localtime":
return mock_localtime
if str(path) == "/etc/timezone":
return mock_timezone
return MagicMock()
mock_path.side_effect = side_effect
assert _os_timezone() is None