import unittest from typing import Any from netscaler_triage.parsing import parse_record class ParsingTests(unittest.TestCase): def test_native_correlation_fields(self) -> None: row = self.parse( 'Sep 28 09:10:11 host bash[1]: return_code="0" trans id 12345 Context name@192.0.2.40' ) self.assertEqual(row["fields"]["return_code"], "0") self.assertEqual(row["fields"]["transaction_id"], "12345") self.assertEqual(row["fields"]["context"], "name@192.0.2.40") row = self.parse('Sep 28 09:10:11 host CMD_EXECUTED 12 - Status "Success"') self.assertEqual(row["fields"]["command_status"], "Success") def test_attacker_username_is_not_update(self) -> None: row = self.parse('Sep 28 09:10:11 host aaad[42]: User "installns upgrade rebooting" failed') self.assertEqual(row["categories"], []) def test_proxy_source(self) -> None: row = self.parse( '192.0.2.40 -> 198.51.100.10 - - [01/Oct/2026:12:02:28 +0000] "GET / HTTP/1.1" 200 5' ) self.assertEqual(row["fields"]["dest"], "198.51.100.10") def parse(self, raw: str, **kwargs: Any) -> dict[str, Any]: return parse_record({"raw": raw}, **kwargs) def test_access_payload_not_update(self) -> None: row = self.parse( '192.0.2.40 - - [01/Oct/2026:12:02:28 +0200] [23] "GET ' '/installns?date=2020-01-01T00:00:00Z HTTP/1.1" 404 23 "-" "x"' ) self.assertEqual(row["timestamp"], "2026-10-01T10:02:28Z") self.assertEqual(row["fields"]["uri"], "/installns?date=2020-01-01T00:00:00Z") self.assertEqual(row["categories"], []) def test_missing_year_and_gmt(self) -> None: row = self.parse( "Sep 30 16:00:54 198.51.100.10 09/30/2026:14:00:54 GMT ns " "0-PPE-0 : message" ) self.assertEqual(row["timestamp"], "2026-09-30T14:00:54Z") self.assertIsNone(self.parse("Sep 30 16:00:54 host bash[1]: installns")["timestamp"]) row = self.parse( "Sep 30 16:00:54 host bash[1]: installns", year=2026, timezone="Europe/Berlin" ) self.assertEqual(row["timestamp"], "2026-09-30T14:00:54Z") self.assertEqual(row["fields"]["update_evidence"], "installer_invocation") def test_historical_explicit_year(self) -> None: row = self.parse( "COLLECTOR::INFOA::Sun Sep 28 09:11:12 2025:Successfully loaded " "configuration(NS13.1-60.20)", year=2026, timezone="UTC", ) self.assertEqual(row["timestamp"], "2025-09-28T09:11:12Z") self.assertEqual(row["fields"]["versions"], ["13.1-60.20"]) self.assertIn("version", row["categories"]) def test_dst_ambiguity(self) -> None: self.assertIsNone( self.parse("2026-10-25 02:30:00 message", timezone="Europe/Berlin")["timestamp"] ) self.assertIsNone( self.parse("2026-03-29 02:30:00 message", timezone="Europe/Berlin")["timestamp"] ) def test_nssetup_version_transition(self) -> None: row = self.parse( "Sep 28 09:10:11 host nssetup[386]: ns_conf_check(): This is an upgrade " "from NetScaler NS13.1 build 50.10 to build 60.20", year=2026, timezone="UTC", ) self.assertEqual(row["fields"]["builds"], ["50.10", "60.20"]) self.assertEqual(row["fields"]["update_relation"], "explicit_upgrade_from_to") row = self.parse( "Sep 28 09:10:11 host nssetup[386]: This is NetScaler version NS13.1, build 60.20" ) self.assertEqual(row["fields"]["versions"], ["13.1-60.20"]) if __name__ == "__main__": unittest.main()