Files
NetAlertX/test/scan/test_currentscan_mac_normalization.py
T

107 lines
3.6 KiB
Python

"""
Tests for MAC normalization on the CurrentScan-promotion path
(server/plugin.py:process_plugin_events()).
scanMac is normally already lowercase by the time this code runs -
plugin_object_class.__init__ normalizes objectPrimaryId via
primary_id_is_mac(), and every current CurrentScan-mapped plugin declares
"type": "device_mac"/"device_name_mac" on that column - so covering it here
too is defense-in-depth for a plugin that omits that type annotation.
scanParentMAC has no such upstream normalization at all (primary_id_is_mac()
only ever checks objectPrimaryId) - this is the column these tests actually
exist to cover, since none of the ~22 real plugins mapping to it call
normalize_mac() in their own script.py.
"""
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from db_test_helpers import ( # noqa: E402
make_plugin_db,
make_plugin_dict,
make_plugin_event_row,
CREATE_CURRENT_SCAN,
)
from plugin import process_plugin_events # noqa: E402
PREFIX = "TESTPLG"
def _plugin_with_parentmac_mapping(prefix: str) -> dict:
"""A plugin dict mapping objectPrimaryId -> scanMac and helpVal1 -> scanParentMAC,
matching the real shape used by e.g. unifi_import/omada_sdn_imp/rest_import."""
plugin = make_plugin_dict(prefix)
plugin["mapped_to_table"] = "CurrentScan"
plugin["database_column_definitions"] = [
{"column": "objectPrimaryId", "mapped_to_column": "scanMac", "type": "device_mac"},
{"column": "helpVal1", "mapped_to_column": "scanParentMAC"},
]
return plugin
def _current_scan_row(conn):
cur = conn.cursor()
cur.execute("SELECT scanMac, scanParentMAC FROM CurrentScan")
return cur.fetchone()
def _plugin_db():
db, conn = make_plugin_db()
conn.execute(CREATE_CURRENT_SCAN)
conn.commit()
return db, conn
class TestScanMacNormalization:
def test_uppercase_scanmac_is_lowercased(self):
db, conn = _plugin_db()
try:
plugin = _plugin_with_parentmac_mapping(PREFIX)
row = make_plugin_event_row(PREFIX, "AA:BB:CC:DD:EE:01")
process_plugin_events(db, plugin, [row])
scan_mac, _ = _current_scan_row(conn)
assert scan_mac == "aa:bb:cc:dd:ee:01"
finally:
conn.close()
class TestScanParentMacNormalization:
"""The real coverage gap: scanParentMAC has no upstream normalization,
unlike scanMac (see module docstring)."""
def test_uppercase_scanparentmac_is_lowercased(self):
db, conn = _plugin_db()
try:
plugin = _plugin_with_parentmac_mapping(PREFIX)
row = make_plugin_event_row(
PREFIX, "aa:bb:cc:dd:ee:01", help_val1="AA:BB:CC:DD:EE:99"
)
process_plugin_events(db, plugin, [row])
_, parent_mac = _current_scan_row(conn)
assert parent_mac == "aa:bb:cc:dd:ee:99"
finally:
conn.close()
def test_empty_scanparentmac_left_empty_not_corrupted(self):
"""normalize_mac(None)/normalize_mac('') must not be applied to a
falsy value - guards the truthy check in process_plugin_events()'s
normalization step against turning an unset parent MAC into garbage
(e.g. normalize_mac(None) would otherwise produce 'no:ne')."""
db, conn = _plugin_db()
try:
plugin = _plugin_with_parentmac_mapping(PREFIX)
row = make_plugin_event_row(
PREFIX, "aa:bb:cc:dd:ee:01", help_val1=""
)
process_plugin_events(db, plugin, [row])
_, parent_mac = _current_scan_row(conn)
assert parent_mac == ""
finally:
conn.close()