FIX: lowercase MAC normalization across project v0.3

Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
jokob-sk
2026-02-07 14:08:14 +11:00
parent 1bacb59044
commit 8538c87fef
12 changed files with 72 additions and 66 deletions

View File

@@ -26,7 +26,7 @@ def client():
@pytest.fixture(scope="session")
def test_mac():
# Generate a unique MAC for each test run
return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
return "aa:bb:cc:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
def auth_headers(token):

View File

@@ -24,7 +24,7 @@ def client():
@pytest.fixture
def test_mac():
# Generate a unique MAC for each test run
return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
return "aa:bb:cc:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
def auth_headers(token):

View File

@@ -26,7 +26,7 @@ def client():
@pytest.fixture
def test_mac():
# Generate a unique MAC for each test run
return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
return "aa:bb:cc:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
def auth_headers(token):
@@ -115,7 +115,7 @@ def test_get_events_totals(client, api_token):
def test_delete_all_events(client, api_token, test_mac):
# create two events
create_event(client, api_token, test_mac)
create_event(client, api_token, "FF:FF:FF:FF:FF:FF")
create_event(client, api_token, "ff:ff:ff:ff:ff:ff")
resp = list_events(client, api_token)
# At least the two we created should be present

View File

@@ -23,7 +23,7 @@ def client():
@pytest.fixture
def test_mac():
# Generate a unique MAC for each test run
return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
return "aa:bb:cc:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
def auth_headers(token):

View File

@@ -24,7 +24,7 @@ def client():
@pytest.fixture
def test_mac():
# Generate a unique MAC for each test run
return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
return "aa:bb:cc:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
def auth_headers(token):

View File

@@ -200,7 +200,7 @@ def test_set_device_alias_not_found(mock_update_col, client, api_token):
mock_update_col.return_value = {"success": False, "error": "Device not found"}
payload = {"alias": "New Device Name"}
response = client.post("/device/FF:FF:FF:FF:FF:FF/set-alias", json=payload, headers=auth_headers(api_token))
response = client.post("/device/ff:ff:ff:ff:ff:ff/set-alias", json=payload, headers=auth_headers(api_token))
assert response.status_code == 200
data = response.get_json()

View File

@@ -19,7 +19,7 @@ def client():
@pytest.fixture
def test_mac():
# Generate a unique MAC for each test run
return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
return "aa:bb:cc:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
def auth_headers(token):

View File

@@ -26,7 +26,7 @@ def client():
@pytest.fixture
def test_mac():
# Generate a unique MAC for each test run
return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
return "aa:bb:cc:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
def auth_headers(token):

View File

@@ -24,7 +24,7 @@ def client():
@pytest.fixture
def test_mac():
# Generate a unique MAC for each test run
return "AA:BB:CC:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
return "aa:bb:cc:" + ":".join(f"{random.randint(0, 255):02X}" for _ in range(3))
def auth_headers(token):

View File

@@ -159,7 +159,7 @@ def test_create_new_devices_sets_sources(scan_db_for_new_devices):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:10",
"aa:bb:cc:dd:ee:10",
"DeviceOne",
"AcmeVendor",
"ARPSCAN",
@@ -176,7 +176,7 @@ def test_create_new_devices_sets_sources(scan_db_for_new_devices):
settings = {
"NEWDEV_devType": "default-type",
"NEWDEV_devParentMAC": "FF:FF:FF:FF:FF:FF",
"NEWDEV_devParentMAC": "ff:ff:ff:ff:ff:ff",
"NEWDEV_devOwner": "owner",
"NEWDEV_devGroup": "group",
"NEWDEV_devComments": "",
@@ -216,7 +216,7 @@ def test_create_new_devices_sets_sources(scan_db_for_new_devices):
devVlanSource
FROM Devices WHERE devMac = ?
""",
("AA:BB:CC:DD:EE:10",),
("aa:bb:cc:dd:ee:10",),
).fetchone()
assert row["devMacSource"] == "ARPSCAN"
@@ -245,7 +245,7 @@ def test_scan_updates_newdev_device_name(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:01",
"aa:bb:cc:dd:ee:01",
"2025-01-01 00:00:00",
0,
"192.168.1.1",
@@ -273,7 +273,7 @@ def test_scan_updates_newdev_device_name(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:01",
"aa:bb:cc:dd:ee:01",
"192.168.1.1",
"TestVendor",
"NBTSCAN",
@@ -299,7 +299,7 @@ def test_scan_updates_newdev_device_name(scan_db, mock_device_handlers):
row = cur.execute(
"SELECT devName FROM Devices WHERE devMac = ?",
("AA:BB:CC:DD:EE:01",),
("aa:bb:cc:dd:ee:01",),
).fetchone()
# Name SHOULD be updated from NEWDEV
@@ -320,7 +320,7 @@ def test_scan_does_not_update_user_field_name(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:02",
"aa:bb:cc:dd:ee:02",
"2025-01-01 00:00:00",
0,
"192.168.1.2",
@@ -348,7 +348,7 @@ def test_scan_does_not_update_user_field_name(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:02",
"aa:bb:cc:dd:ee:02",
"192.168.1.2",
"TestVendor",
"NBTSCAN",
@@ -374,7 +374,7 @@ def test_scan_does_not_update_user_field_name(scan_db, mock_device_handlers):
row = cur.execute(
"SELECT devName FROM Devices WHERE devMac = ?",
("AA:BB:CC:DD:EE:02",),
("aa:bb:cc:dd:ee:02",),
).fetchone()
# Name should NOT be updated because it's USER-owned
@@ -395,7 +395,7 @@ def test_scan_does_not_update_locked_field(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:03",
"aa:bb:cc:dd:ee:03",
"2025-01-01 00:00:00",
0,
"192.168.1.3",
@@ -423,7 +423,7 @@ def test_scan_does_not_update_locked_field(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:03",
"aa:bb:cc:dd:ee:03",
"192.168.1.3",
"TestVendor",
"NBTSCAN",
@@ -449,7 +449,7 @@ def test_scan_does_not_update_locked_field(scan_db, mock_device_handlers):
row = cur.execute(
"SELECT devName FROM Devices WHERE devMac = ?",
("AA:BB:CC:DD:EE:03",),
("aa:bb:cc:dd:ee:03",),
).fetchone()
# Name should NOT be updated because it's LOCKED
@@ -470,7 +470,7 @@ def test_scan_updates_empty_vendor_field(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:04",
"aa:bb:cc:dd:ee:04",
"2025-01-01 00:00:00",
0,
"192.168.1.4",
@@ -498,7 +498,7 @@ def test_scan_updates_empty_vendor_field(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:04",
"aa:bb:cc:dd:ee:04",
"192.168.1.4",
"Apple Inc.",
"ARPSCAN",
@@ -524,7 +524,7 @@ def test_scan_updates_empty_vendor_field(scan_db, mock_device_handlers):
row = cur.execute(
"SELECT devVendor FROM Devices WHERE devMac = ?",
("AA:BB:CC:DD:EE:04",),
("aa:bb:cc:dd:ee:04",),
).fetchone()
# Vendor SHOULD be updated
@@ -546,7 +546,7 @@ def test_scan_updates_ip_addresses(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:05",
"aa:bb:cc:dd:ee:05",
"2025-01-01 00:00:00",
0,
"",
@@ -576,7 +576,7 @@ def test_scan_updates_ip_addresses(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:05",
"aa:bb:cc:dd:ee:05",
"192.168.1.100",
"Vendor",
"ARPSCAN",
@@ -603,7 +603,7 @@ def test_scan_updates_ip_addresses(scan_db, mock_device_handlers):
row = cur.execute(
"SELECT devLastIP, devPrimaryIPv4, devPrimaryIPv6 FROM Devices WHERE devMac = ?",
("AA:BB:CC:DD:EE:05",),
("aa:bb:cc:dd:ee:05",),
).fetchone()
# IPv4 should be set
@@ -627,7 +627,7 @@ def test_scan_updates_ipv6_without_changing_ipv4(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:06",
"aa:bb:cc:dd:ee:06",
"2025-01-01 00:00:00",
0,
"192.168.1.101",
@@ -657,7 +657,7 @@ def test_scan_updates_ipv6_without_changing_ipv4(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:06",
"aa:bb:cc:dd:ee:06",
"fe80::1",
"Vendor",
"ARPSCAN",
@@ -684,7 +684,7 @@ def test_scan_updates_ipv6_without_changing_ipv4(scan_db, mock_device_handlers):
row = cur.execute(
"SELECT devPrimaryIPv4, devPrimaryIPv6 FROM Devices WHERE devMac = ?",
("AA:BB:CC:DD:EE:06",),
("aa:bb:cc:dd:ee:06",),
).fetchone()
# IPv4 should remain, IPv6 should be set
@@ -706,7 +706,7 @@ def test_scan_updates_presence_status(scan_db, mock_device_handlers):
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
"AA:BB:CC:DD:EE:07",
"aa:bb:cc:dd:ee:07",
"2025-01-01 00:00:00",
1, # Was online
"192.168.1.102",
@@ -737,7 +737,7 @@ def test_scan_updates_presence_status(scan_db, mock_device_handlers):
row = cur.execute(
"SELECT devPresentLastScan FROM Devices WHERE devMac = ?",
("AA:BB:CC:DD:EE:07",),
("aa:bb:cc:dd:ee:07",),
).fetchone()
# Device should be marked as offline
@@ -750,10 +750,10 @@ def test_scan_multiple_devices_mixed_sources(scan_db, mock_device_handlers):
devices_data = [
# (MAC, Name, NameSource, Vendor, VendorSource)
("AA:BB:CC:DD:EE:11", "Device1", "NEWDEV", "", "NEWDEV"), # Both updatable
("AA:BB:CC:DD:EE:12", "My Device", "USER", "OldVendor", "NEWDEV"), # Name protected
("AA:BB:CC:DD:EE:13", "Locked Device", "LOCKED", "", "NEWDEV"), # Name locked
("AA:BB:CC:DD:EE:14", "Device4", "ARPSCAN", "", "NEWDEV"), # Name from plugin
("aa:bb:cc:dd:ee:11", "Device1", "NEWDEV", "", "NEWDEV"), # Both updatable
("aa:bb:cc:dd:ee:12", "My Device", "USER", "OldVendor", "NEWDEV"), # Name protected
("aa:bb:cc:dd:ee:13", "Locked Device", "LOCKED", "", "NEWDEV"), # Name locked
("aa:bb:cc:dd:ee:14", "Device4", "ARPSCAN", "", "NEWDEV"), # Name from plugin
]
for mac, name, name_src, vendor, vendor_src in devices_data:
@@ -786,10 +786,10 @@ def test_scan_multiple_devices_mixed_sources(scan_db, mock_device_handlers):
# Scan discovers all devices with new data
scan_entries = [
("AA:BB:CC:DD:EE:11", "192.168.1.1", "Apple Inc.", "ScanPlugin", "ScannedDevice1"),
("AA:BB:CC:DD:EE:12", "192.168.1.2", "Samsung", "ScanPlugin", "ScannedDevice2"),
("AA:BB:CC:DD:EE:13", "192.168.1.3", "Sony", "ScanPlugin", "ScannedDevice3"),
("AA:BB:CC:DD:EE:14", "192.168.1.4", "LG", "ScanPlugin", "ScannedDevice4"),
("aa:bb:cc:dd:ee:11", "192.168.1.1", "Apple Inc.", "ScanPlugin", "ScannedDevice1"),
("aa:bb:cc:dd:ee:12", "192.168.1.2", "Samsung", "ScanPlugin", "ScannedDevice2"),
("aa:bb:cc:dd:ee:13", "192.168.1.3", "Sony", "ScanPlugin", "ScannedDevice3"),
("aa:bb:cc:dd:ee:14", "192.168.1.4", "LG", "ScanPlugin", "ScannedDevice4"),
]
for mac, ip, vendor, scan_method, name in scan_entries:
@@ -815,10 +815,10 @@ def test_scan_multiple_devices_mixed_sources(scan_db, mock_device_handlers):
# Check results
results = {
"AA:BB:CC:DD:EE:11": {"name": "Device1", "vendor": "Apple Inc."}, # Name already set, won't update
"AA:BB:CC:DD:EE:12": {"name": "My Device", "vendor": "Samsung"}, # Name protected (USER)
"AA:BB:CC:DD:EE:13": {"name": "Locked Device", "vendor": "Sony"}, # Name locked
"AA:BB:CC:DD:EE:14": {"name": "Device4", "vendor": "LG"}, # Name already from plugin, won't update
"aa:bb:cc:dd:ee:11": {"name": "Device1", "vendor": "Apple Inc."}, # Name already set, won't update
"aa:bb:cc:dd:ee:12": {"name": "My Device", "vendor": "Samsung"}, # Name protected (USER)
"aa:bb:cc:dd:ee:13": {"name": "Locked Device", "vendor": "Sony"}, # Name locked
"aa:bb:cc:dd:ee:14": {"name": "Device4", "vendor": "LG"}, # Name already from plugin, won't update
}
for mac, expected in results.items():

View File

@@ -24,10 +24,10 @@ def mock_ip_handlers():
def test_valid_ipv4_format_accepted(scan_db, mock_ip_handlers):
"""Valid IPv4 address should be accepted and set as primary IPv4."""
cur = scan_db.cursor()
cur.execute("INSERT INTO Devices (devMac, devName) VALUES (?, ?)", ("AA:BB:CC:DD:EE:01", "Device1"))
cur.execute("INSERT INTO Devices (devMac, devName) VALUES (?, ?)", ("ff:ff:cc:dd:ee:01", "Device1"))
cur.execute(
"INSERT INTO CurrentScan (scanMac, scanLastIP, scanSourcePlugin, scanLastConnection) VALUES (?, ?, ?, ?)",
("AA:BB:CC:DD:EE:01", "192.168.1.100", "ARPSCAN", "2025-01-01 01:00:00")
("ff:ff:cc:dd:ee:01", "192.168.1.100", "ARPSCAN", "2025-01-01 01:00:00")
)
scan_db.commit()
@@ -35,7 +35,7 @@ def test_valid_ipv4_format_accepted(scan_db, mock_ip_handlers):
device_handling.update_devices_data_from_scan(db)
device_handling.update_ipv4_ipv6(db)
row = cur.execute("SELECT devLastIP, devPrimaryIPv4 FROM Devices WHERE devMac = ?", ("AA:BB:CC:DD:EE:01",)).fetchone()
row = cur.execute("SELECT devLastIP, devPrimaryIPv4 FROM Devices WHERE devMac = ?", ("ff:ff:cc:dd:ee:01",)).fetchone()
assert row["devLastIP"] == "192.168.1.100"
assert row["devPrimaryIPv4"] == "192.168.1.100"
@@ -43,10 +43,10 @@ def test_valid_ipv4_format_accepted(scan_db, mock_ip_handlers):
def test_valid_ipv6_format_accepted(scan_db, mock_ip_handlers):
"""Valid IPv6 address should be accepted and set as primary IPv6."""
cur = scan_db.cursor()
cur.execute("INSERT INTO Devices (devMac) VALUES (?)", ("AA:BB:CC:DD:EE:02",))
cur.execute("INSERT INTO Devices (devMac) VALUES (?)", ("ff:ff:cc:dd:ee:02",))
cur.execute(
"INSERT INTO CurrentScan (scanMac, scanLastIP, scanSourcePlugin, scanLastConnection) VALUES (?, ?, ?, ?)",
("AA:BB:CC:DD:EE:02", "fe80::1", "ARPSCAN", "2025-01-01 01:00:00")
("ff:ff:cc:dd:ee:02", "fe80::1", "ARPSCAN", "2025-01-01 01:00:00")
)
scan_db.commit()
@@ -54,21 +54,21 @@ def test_valid_ipv6_format_accepted(scan_db, mock_ip_handlers):
device_handling.update_devices_data_from_scan(db)
device_handling.update_ipv4_ipv6(db)
row = cur.execute("SELECT devPrimaryIPv6 FROM Devices WHERE devMac = ?", ("AA:BB:CC:DD:EE:02",)).fetchone()
row = cur.execute("SELECT devPrimaryIPv6 FROM Devices WHERE devMac = ?", ("ff:ff:cc:dd:ee:02",)).fetchone()
assert row["devPrimaryIPv6"] == "fe80::1"
def test_invalid_ip_values_rejected(scan_db, mock_ip_handlers):
"""Invalid IP values like (unknown), null, empty should be rejected."""
cur = scan_db.cursor()
cur.execute("INSERT INTO Devices (devMac, devPrimaryIPv4) VALUES (?, ?)", ("AA:BB:CC:DD:EE:03", "192.168.1.50"))
cur.execute("INSERT INTO Devices (devMac, devPrimaryIPv4) VALUES (?, ?)", ("ff:ff:cc:dd:ee:03", "192.168.1.50"))
invalid_ips = ["", "null", "(unknown)", "(Unknown)"]
for invalid_ip in invalid_ips:
cur.execute("DELETE FROM CurrentScan")
cur.execute(
"INSERT INTO CurrentScan (scanMac, scanLastIP, scanSourcePlugin, scanLastConnection) VALUES (?, ?, ?, ?)",
("AA:BB:CC:DD:EE:03", invalid_ip, "ARPSCAN", "2025-01-01 01:00:00")
("ff:ff:cc:dd:ee:03", invalid_ip, "ARPSCAN", "2025-01-01 01:00:00")
)
scan_db.commit()
@@ -76,7 +76,7 @@ def test_invalid_ip_values_rejected(scan_db, mock_ip_handlers):
device_handling.update_devices_data_from_scan(db)
device_handling.update_ipv4_ipv6(db)
row = cur.execute("SELECT devPrimaryIPv4 FROM Devices WHERE devMac = ?", ("AA:BB:CC:DD:EE:03",)).fetchone()
row = cur.execute("SELECT devPrimaryIPv4 FROM Devices WHERE devMac = ?", ("ff:ff:cc:dd:ee:03",)).fetchone()
assert row["devPrimaryIPv4"] == "192.168.1.50", f"Failed on {invalid_ip}"
@@ -89,7 +89,7 @@ def test_ipv4_then_ipv6_scan_updates_primary_ips(scan_db, mock_ip_handlers):
cur = scan_db.cursor()
# 1⃣ Create device
cur.execute("INSERT INTO Devices (devMac) VALUES (?)", ("AA:BB:CC:DD:EE:04",))
cur.execute("INSERT INTO Devices (devMac) VALUES (?)", ("ff:ff:cc:dd:ee:04",))
scan_db.commit()
db = Mock(sql_connection=scan_db, sql=cur)
@@ -97,7 +97,7 @@ def test_ipv4_then_ipv6_scan_updates_primary_ips(scan_db, mock_ip_handlers):
# 2⃣ First scan: IPv4
cur.execute(
"INSERT INTO CurrentScan (scanMac, scanLastIP, scanSourcePlugin, scanLastConnection) VALUES (?, ?, ?, ?)",
("AA:BB:CC:DD:EE:04", "192.168.1.100", "ARPSCAN", "2025-01-01 01:00:00")
("ff:ff:cc:dd:ee:04", "192.168.1.100", "ARPSCAN", "2025-01-01 01:00:00")
)
scan_db.commit()
@@ -109,7 +109,7 @@ def test_ipv4_then_ipv6_scan_updates_primary_ips(scan_db, mock_ip_handlers):
cur.execute("DELETE FROM CurrentScan")
cur.execute(
"INSERT INTO CurrentScan (scanMac, scanLastIP, scanSourcePlugin, scanLastConnection) VALUES (?, ?, ?, ?)",
("AA:BB:CC:DD:EE:04", "fe80::1", "IPv6SCAN", "2025-01-01 02:00:00")
("ff:ff:cc:dd:ee:04", "fe80::1", "IPv6SCAN", "2025-01-01 02:00:00")
)
scan_db.commit()
@@ -120,7 +120,7 @@ def test_ipv4_then_ipv6_scan_updates_primary_ips(scan_db, mock_ip_handlers):
# 4⃣ Verify results
row = cur.execute(
"SELECT devLastIP, devPrimaryIPv4, devPrimaryIPv6 FROM Devices WHERE devMac = ?",
("AA:BB:CC:DD:EE:04",)
("ff:ff:cc:dd:ee:04",)
).fetchone()
assert row["devLastIP"] == "fe80::1" # Latest scan IP (IPv6)
@@ -134,7 +134,7 @@ def test_ipv4_address_format_variations(scan_db, mock_ip_handlers):
ipv4_addresses = ["1.1.1.1", "127.0.0.1", "192.168.1.1", "255.255.255.255"]
for idx, ipv4 in enumerate(ipv4_addresses):
mac = f"AA:BB:CC:DD:11:{idx:02X}"
mac = f"AA:BB:CC:DD:11:{idx:02X}".lower()
cur.execute("INSERT INTO Devices (devMac) VALUES (?)", (mac,))
cur.execute("INSERT INTO CurrentScan (scanMac, scanLastIP, scanSourcePlugin, scanLastConnection) VALUES (?, ?, ?, ?)",
(mac, ipv4, "SCAN", "2025-01-01 01:00:00"))

View File

@@ -2,23 +2,29 @@ from front.plugins.plugin_helper import is_mac, normalize_mac
def test_is_mac_accepts_wildcard():
assert is_mac("AA:BB:CC:*") is True
assert is_mac("aa-bb-cc:*") is True # mixed separator
# is_mac checks structure, so it should still return True
assert is_mac("aa:bb:cc:*") is True
assert is_mac("AA-BB-CC:*") is True # mixed case/separator should still be recognized
assert is_mac("00:11:22:33:44:55") is True
assert is_mac("00-11-22-33-44-55") is True
assert is_mac("not-a-mac") is False
def test_normalize_mac_preserves_wildcard():
assert normalize_mac("aa:bb:cc:*") == "AA:BB:CC:*"
assert normalize_mac("aa-bb-cc-*") == "AA:BB:CC:*"
# UPDATED: Expected results are now lowercase to match the DB standard
assert normalize_mac("aa:bb:cc:*") == "aa:bb:cc:*"
assert normalize_mac("AA-BB-CC-*") == "aa:bb:cc:*"
# Call once and assert deterministic result
result = normalize_mac("aabbcc*")
assert result == "AA:BB:CC:*", f"Expected 'AA:BB:CC:*' but got '{result}'"
assert normalize_mac("aa:bb:cc:dd:ee:ff") == "aa:bb:cc:dd:ee:ff"
assert result == "aa:bb:cc:*", f"Expected 'aa:bb:cc:*' but got '{result}'"
# Ensure full MACs are lowercase too
assert normalize_mac("AA:BB:CC:DD:EE:FF") == "aa:bb:cc:dd:ee:ff"
def test_normalize_mac_preserves_internet_root():
# Stays lowercase
assert normalize_mac("internet") == "internet"
assert normalize_mac("Internet") == "internet"
assert normalize_mac("INTERNET") == "internet"
assert normalize_mac("INTERNET") == "internet"