68 lines
2.7 KiB
Python
68 lines
2.7 KiB
Python
|
|
import json
|
||
|
|
import unittest
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
from collectors.mounts import MountsCollector
|
||
|
|
from reports.html_report import HTMLReportGenerator
|
||
|
|
from validators.compare import compare_snapshots
|
||
|
|
|
||
|
|
|
||
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||
|
|
|
||
|
|
|
||
|
|
class ComparatorExampleTests(unittest.TestCase):
|
||
|
|
def test_example_comparison_detects_expected_failure(self):
|
||
|
|
before = json.loads((PROJECT_ROOT / "examples" / "before.json").read_text())
|
||
|
|
after = json.loads((PROJECT_ROOT / "examples" / "after.json").read_text())
|
||
|
|
|
||
|
|
comparison = compare_snapshots(before, after)
|
||
|
|
|
||
|
|
self.assertFalse(comparison["validation_results"]["passed"])
|
||
|
|
self.assertEqual(comparison["validation_results"]["result"], "FAIL")
|
||
|
|
self.assertGreater(comparison["summary"]["total_changes"], 0)
|
||
|
|
|
||
|
|
|
||
|
|
class HtmlReportTests(unittest.TestCase):
|
||
|
|
def test_report_escapes_untrusted_snapshot_content(self):
|
||
|
|
report = HTMLReportGenerator().build_html_content({
|
||
|
|
"metadata": {"comparison_id": "<script>alert(1)</script>"},
|
||
|
|
"summary": {
|
||
|
|
"total_systems": 1,
|
||
|
|
"systems_with_changes": 1,
|
||
|
|
"total_changes": 1,
|
||
|
|
"changes_by_type": {"services": 1},
|
||
|
|
"most_affected_systems": [("<img src=x onerror=alert(1)>", 1)],
|
||
|
|
},
|
||
|
|
"differences": {},
|
||
|
|
"risk_assessment": {"overall_risk": "low", "risk_factors": [], "critical_changes": [], "recommendations": ["Review <b>change</b>"]},
|
||
|
|
"validation_results": {"passed": True, "checks": []},
|
||
|
|
})
|
||
|
|
|
||
|
|
self.assertNotIn("<script>alert(1)</script>", report)
|
||
|
|
self.assertNotIn("<img src=x onerror=alert(1)>", report)
|
||
|
|
self.assertIn("<script>alert(1)</script>", report)
|
||
|
|
self.assertIn("<b>change</b>", report)
|
||
|
|
|
||
|
|
|
||
|
|
class CollectorParserTests(unittest.TestCase):
|
||
|
|
def test_mount_parser_handles_standard_mount_output(self):
|
||
|
|
output = "/dev/sda1 on / type ext4 (rw,relatime)\nproc on /proc type proc (rw,nosuid,nodev,noexec,relatime)\n"
|
||
|
|
mounts = MountsCollector().parse_mount_output(output)
|
||
|
|
|
||
|
|
self.assertEqual(mounts[0]["device"], "/dev/sda1")
|
||
|
|
self.assertEqual(mounts[0]["mountpoint"], "/")
|
||
|
|
self.assertEqual(mounts[0]["fstype"], "ext4")
|
||
|
|
|
||
|
|
def test_df_parser_handles_gigabyte_output(self):
|
||
|
|
output = "Filesystem 1G-blocks Used Available Use% Mounted\n/dev/sda1 100G 45G 55G 45% /\n"
|
||
|
|
stats = MountsCollector().parse_df_output(output)
|
||
|
|
|
||
|
|
self.assertEqual(stats["1g-blocks"], 100.0)
|
||
|
|
self.assertEqual(stats["used"], 45.0)
|
||
|
|
self.assertEqual(stats["available"], 55.0)
|
||
|
|
self.assertEqual(stats["use_percent"], 45)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
unittest.main()
|