mirror of
https://github.com/Horizontal42/netsleuth.git
synced 2026-11-10 18:02:04 +03:00
New metrics.py: collect_metrics() does the per-section extraction a flat dict walk can't (latency needs label/host/method, TLS label/host, path hops target/ttl/ip/asn), producing a flat Metric list that render_prometheus() and render_csv() each format in about 15 lines. Simpler than treating them as two separate renderers. FORMAT_EXTENSIONS gained "prom"/"csv" as the single wiring point both parse_formats() and Output._normalize_formats() already key off of. New history.py finds a previous JSON report for the same ASN by reusing the exact filename convention exporter.report_filename() already writes, so the lookup key can't drift from what's on disk. Wired into diagnose() before write_report() - a compact vs-previous-run summary (compare.py::render_diff_brief(), new) prints automatically whenever this run writes JSON and an earlier one exists for the same network; silent on every other case (first run, prior run wrote no JSON prints one note instead of guessing). New --no-auto-diff escapes it per run, history.auto_diff in config disables it entirely. New trend.py aggregates N saved JSON reports into per-label sparkline series via --trend N - read-only, and it doesn't touch the network to find "this network's" history either: history.latest_key() just reads it off the newest report filename already on disk. Growing FORMAT_EXTENSIONS to 5 entries broke three pre-existing tests that hardcoded the old 3-format set; fixed in this commit. Live-tested: prom/csv artifacts render correctly, auto-diff fired on a second run, --trend 3 produced readable output, --compare unaffected. Part of plans/zesty-zooming-wilkinson.md (gitignored).
85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
import typer
|
|
|
|
from netsleuth.cli import format_siblings, parse_formats
|
|
|
|
DEFAULT = frozenset({"md"})
|
|
|
|
|
|
def test_no_flags_returns_the_default():
|
|
assert parse_formats([], ru=False, json_flag=False, default=DEFAULT) == DEFAULT
|
|
|
|
|
|
def test_json_shortcut_selects_json_only():
|
|
assert parse_formats([], ru=False, json_flag=True, default=DEFAULT) == frozenset({"json"})
|
|
|
|
|
|
def test_ru_shortcut_selects_ru_md_only():
|
|
assert parse_formats([], ru=True, json_flag=False, default=DEFAULT) == frozenset({"ru-md"})
|
|
|
|
|
|
def test_json_and_format_md_stack():
|
|
assert parse_formats(["md"], ru=False, json_flag=True, default=DEFAULT) == frozenset({"md", "json"})
|
|
|
|
|
|
def test_repeated_format_flags_union():
|
|
assert parse_formats(["md", "json"], ru=False, json_flag=False, default=DEFAULT) == frozenset(
|
|
{"md", "json"}
|
|
)
|
|
|
|
|
|
def test_comma_separated_single_flag():
|
|
assert parse_formats(["md,json"], ru=False, json_flag=False, default=DEFAULT) == frozenset(
|
|
{"md", "json"}
|
|
)
|
|
|
|
|
|
def test_all_expands_to_every_known_format():
|
|
assert parse_formats(["all"], ru=False, json_flag=False, default=DEFAULT) == frozenset(
|
|
{"md", "ru-md", "json", "prom", "csv"}
|
|
)
|
|
|
|
|
|
def test_none_alone_means_write_nothing():
|
|
assert parse_formats(["none"], ru=False, json_flag=False, default=DEFAULT) == frozenset()
|
|
|
|
|
|
def test_none_combined_with_another_format_is_an_error():
|
|
with pytest.raises(typer.BadParameter):
|
|
parse_formats(["none,md"], ru=False, json_flag=False, default=DEFAULT)
|
|
|
|
|
|
def test_unknown_format_is_an_error():
|
|
with pytest.raises(typer.BadParameter):
|
|
parse_formats(["pdf"], ru=False, json_flag=False, default=DEFAULT)
|
|
|
|
|
|
def test_case_and_whitespace_are_normalized():
|
|
assert parse_formats([" MD ", "JSON"], ru=False, json_flag=False, default=DEFAULT) == frozenset(
|
|
{"md", "json"}
|
|
)
|
|
|
|
|
|
def test_order_of_flags_never_changes_the_result():
|
|
a = parse_formats(["json", "md"], ru=False, json_flag=False, default=DEFAULT)
|
|
b = parse_formats(["md", "json"], ru=False, json_flag=False, default=DEFAULT)
|
|
assert a == b
|
|
|
|
|
|
def test_format_siblings_cross_link_when_both_languages_selected():
|
|
result = format_siblings(frozenset({"md", "ru-md"}), "report.md", "report.ru.md")
|
|
assert result == ("report.ru.md", "report.md")
|
|
|
|
|
|
def test_format_siblings_are_none_when_only_english_selected():
|
|
assert format_siblings(frozenset({"md"}), "report.md", "report.ru.md") == (None, None)
|
|
|
|
|
|
def test_format_siblings_are_none_when_only_russian_selected():
|
|
assert format_siblings(frozenset({"ru-md"}), "report.md", "report.ru.md") == (None, None)
|
|
|
|
|
|
def test_format_siblings_are_none_when_neither_markdown_selected():
|
|
assert format_siblings(frozenset({"json"}), "report.md", "report.ru.md") == (None, None)
|