Files
napalm-yealink/tests/test_fingerprint.py
Christian Manivong 33d07bed58 fix: inherit PhoneDriver, and stop asserting a contract the driver rejected
Closes netork#117.

A Yealink is a desk phone. It inherited AccessPointDriver because nothing better
existed, and netOrk reads that role to populate its wireless page, its AP
profile pickers and its SSID drift view — so a phone appeared in all three.
napalm-device-types now has PhoneDriver. TYPE_LABEL comes from it, so the local
override is gone.

The two failing fingerprint tests were asserting the opposite of a deliberate
decision. HTTP_FINGERPRINT carries "yealink" as a heavy but *not* mandatory
rule, with the reason written next to it: some models answer / with a redirect
to their API page, whose body says "yealink" nowhere, and a mandatory rule
disqualifies the driver whenever its pattern is absent. Making it mandatory
would rule out a real phone.

The tests demanded it be mandatory, and the Cisco test then asserted `not
all(...)` over an empty list, which is False. Both now check the property that
actually protects against a false match: none of this driver's patterns appear
on a Cisco page, so it contributes no score and never wins.
2026-08-21 13:07:37 +07:00

61 lines
2.2 KiB
Python

"""Fingerprint tests for YealinkDriver."""
from napalm_device_types import DeviceTypeDriver, PhoneDriver, role_keys_of
from napalm_yealink import YealinkDriver
def test_yealink_is_device_type_driver():
assert issubclass(YealinkDriver, DeviceTypeDriver)
def test_type_label():
assert YealinkDriver.TYPE_LABEL == "Phone"
def test_vendor():
assert YealinkDriver.VENDOR == "Yealink"
def test_driver_name():
assert YealinkDriver.DRIVER_NAME == "yealink"
def test_snmp_oid_prefix():
assert YealinkDriver.SNMP_OBJECT_ID_PREFIX == "1.3.6.1.4.1.37403"
def test_yealink_pattern_is_decisive_but_not_mandatory():
"""A mandatory rule disqualifies the driver whenever the pattern is absent.
Some Yealink models answer / with a redirect to their API page, whose body
carries no "yealink" anywhere — making the rule mandatory would rule out a
real Yealink phone. It carries decisive weight instead, so a page that does
say "yealink" still wins by a wide margin.
"""
yealink_rules = [r for r in YealinkDriver.HTTP_FINGERPRINT if r.pattern == "yealink"]
assert yealink_rules, "the vendor pattern must be present at all"
assert all(not r.mandatory for r in yealink_rules)
assert max(r.weight for r in yealink_rules) >= 10.0
def test_fingerprint_matches_t58_title():
"""'Yealink T58 Phone' im Titel → mandatory 'yealink' trifft zu."""
combined = "yealink t58 phone nginx "
mandatory = [r for r in YealinkDriver.HTTP_FINGERPRINT if r.mandatory]
assert all(r.pattern in combined for r in mandatory)
def test_fingerprint_scores_nothing_on_a_cisco_page():
"""Without a mandatory rule, what keeps a Cisco phone out is that none of
Yealink's patterns match it at all — so the driver contributes zero score
and never wins."""
combined = "cisco ip phone cp-8841 "
assert not any(r.pattern in combined for r in YealinkDriver.HTTP_FINGERPRINT)
def test_declares_the_phone_role_not_access_point():
"""A desk phone used to inherit AccessPointDriver for want of anywhere
better, which put it in netOrk's wireless page and AP profile pickers."""
assert issubclass(YealinkDriver, PhoneDriver)
assert role_keys_of(YealinkDriver) == ["phone"]