mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-09-16 08:10:15 -04:00
Fix DOCKERDISC_HOST_MAC docs and strengthen case-insensitivity test
resolve_host_mac() returns the manually configured MAC immediately, with no Socket Proxy /info call at all - the config.json text still described it as a fallback used only when auto-detection fails. Reworded both the setting's own description and the parent "Docker hosts" description to match actual behavior. The case-insensitivity regression test for lookup_device_mac() stubbed DeviceInstance.getByMac() to return a fixed row regardless of input, so it passed even without exercising real collation - functionally a duplicate of test_lookup_device_mac_found. Replaced it with a delegation check, and added real SQLite-backed coverage for DeviceInstance.getByMac()'s case-insensitivity in test/backend/test_device_instance.py. That surfaced a gap in the shared db_test_helpers.py fixture: its Devices.devMac column was missing the COLLATE NOCASE that the real schema declares, so it could not have exercised this behavior. Fixed the fixture to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011meLPKCzVpdZyAUfv5U6mm
This commit is contained in:
1 parent
d512e5d84e
commit
091e648e88
4 files changed
+48
-18
No files matched your search
@@ -544,13 +544,13 @@
|
||||
"name": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Docker Host MAC Address (Fallback)"
|
||||
"string": "Docker Host MAC Address (Manual)"
|
||||
}
|
||||
],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "Manual fallback physical MAC address of the Docker host, used if auto-detecting it via the Socket Proxy <code>/info</code> endpoint fails. The host must already exist as a device in NetAlertX (found via ARP/Nmap) - this plugin never creates it."
|
||||
"string": "Manually configured physical MAC address of the Docker host. When set, it is used immediately - no Socket Proxy <code>/info</code> call is made. Leave blank to auto-detect the host via hostname matching instead. The host must already exist as a device in NetAlertX (found via ARP/Nmap) - this plugin never creates it."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -620,7 +620,7 @@
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string": "One entry per Docker host to track. Each entry pairs a read-only Docker Socket Proxy URL with that host's device (auto-detected, or entered manually as a fallback). Every container found on a host is listed under that host's own Device Details -> Plugins -> DOCKERDISC tab - the host device must already exist in NetAlertX (via ARP/Nmap); this plugin never creates devices."
|
||||
"string": "One entry per Docker host to track. Each entry pairs a read-only Docker Socket Proxy URL with that host's device, matched either by a manually configured MAC (used immediately when set) or by auto-detected hostname. Every container found on a host is listed under that host's own Device Details -> Plugins -> DOCKERDISC tab - the host device must already exist in NetAlertX (via ARP/Nmap); this plugin never creates devices."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -60,5 +60,37 @@ class TestGetAllByName(unittest.TestCase):
|
||||
self.assertEqual(results, [])
|
||||
|
||||
|
||||
class TestGetByMac(unittest.TestCase):
|
||||
"""devMac is declared COLLATE NOCASE at the column level (unlike
|
||||
devName), so getByMac() relies on the schema rather than applying its
|
||||
own COLLATE clause - this exercises that guarantee against a real
|
||||
SQLite connection, not a mock."""
|
||||
|
||||
def setUp(self):
|
||||
self.conn = make_db()
|
||||
insert_device_from_dict(self.conn, make_device_dict("aa:bb:cc:dd:ee:ff"))
|
||||
self.conn.commit()
|
||||
|
||||
def _instance(self):
|
||||
from models.device_instance import DeviceInstance
|
||||
inst = DeviceInstance()
|
||||
|
||||
def _fetchone(q, p=()):
|
||||
row = self.conn.execute(q, p).fetchone()
|
||||
return dict(row) if row else None
|
||||
inst._fetchone = _fetchone
|
||||
return inst
|
||||
|
||||
def test_case_insensitive_match(self):
|
||||
inst = self._instance()
|
||||
result = inst.getByMac("AA:BB:CC:DD:EE:FF")
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(result["devMac"], "aa:bb:cc:dd:ee:ff")
|
||||
|
||||
def test_no_match_returns_none(self):
|
||||
inst = self._instance()
|
||||
self.assertIsNone(inst.getByMac("00:00:00:00:00:00"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -28,7 +28,7 @@ from db.db_history import ensure_deviceshistory_table, ensure_deviceshistory_tri
|
||||
|
||||
CREATE_DEVICES = """
|
||||
CREATE TABLE IF NOT EXISTS Devices (
|
||||
devMac TEXT PRIMARY KEY,
|
||||
devMac TEXT PRIMARY KEY COLLATE NOCASE,
|
||||
devName TEXT,
|
||||
devOwner TEXT,
|
||||
devType TEXT,
|
||||
|
||||
@@ -445,20 +445,18 @@ def test_lookup_device_mac_not_found():
|
||||
assert dockerdisc.lookup_device_mac("aa:bb:cc:dd:ee:ff") is False
|
||||
|
||||
|
||||
def test_lookup_device_mac_found_regardless_of_stored_mac_case():
|
||||
"""The plugin always passes a lowercase, normalize_mac()'d value in -
|
||||
this only guards that lookup_device_mac() doesn't do anything of its
|
||||
own (e.g. an exact-string comparison) that would undo whatever
|
||||
case-insensitivity DeviceInstance.getByMac() provides. The real
|
||||
guarantee is schema-level - Devices.devMac is declared
|
||||
`COLLATE NOCASE` (server/db/schema/app.sql), which is exactly why
|
||||
getByMac() itself doesn't need to apply it explicitly (unlike
|
||||
getAllByName(), which does - devName has no such column collation;
|
||||
see that method's docstring and test/backend/test_device_instance.py).
|
||||
This test's stub can't exercise real SQLite collation, only that this
|
||||
function's own logic is agnostic to it."""
|
||||
with patch.object(dockerdisc, "DeviceInstance", _stub_device_instance(get_by_mac={"devMac": "AA:BB:CC:DD:EE:FF"})):
|
||||
assert dockerdisc.lookup_device_mac("aa:bb:cc:dd:ee:ff") is True
|
||||
def test_lookup_device_mac_passes_mac_through_unchanged():
|
||||
"""lookup_device_mac() must not do any of its own case massaging - it
|
||||
delegates entirely to DeviceInstance.getByMac(), which relies on
|
||||
Devices.devMac's schema-level `COLLATE NOCASE` (server/db/schema/app.sql)
|
||||
for case-insensitive matching. That guarantee is exercised against a
|
||||
real SQLite connection in test/backend/test_device_instance.py's
|
||||
TestGetByMac; a mocked DeviceInstance can't exercise real collation, so
|
||||
this test only checks that the mac argument reaches getByMac() as-is."""
|
||||
stub = _stub_device_instance(get_by_mac={"devMac": "aa:bb:cc:dd:ee:ff"})
|
||||
with patch.object(dockerdisc, "DeviceInstance", stub):
|
||||
dockerdisc.lookup_device_mac("AA:BB:CC:DD:EE:FF")
|
||||
stub.return_value.getByMac.assert_called_once_with("AA:BB:CC:DD:EE:FF")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user