diff --git a/docs/source/contributing/conventions/protocol-family-grouping.rst b/docs/source/contributing/conventions/protocol-family-grouping.rst index 313b9fa75a..1fcb958839 100644 --- a/docs/source/contributing/conventions/protocol-family-grouping.rst +++ b/docs/source/contributing/conventions/protocol-family-grouping.rst @@ -107,7 +107,7 @@ Member Shapes code and reports ARP, RARP, DRARP or InARP through :attr:`~pcapkit.protocols.protocol.Protocol.alias` -Nothing dispatches to :class:`~pcapkit.protocols.link.arp.InARP` ``('InARP',)``: +Nothing dispatches to :class:`~pcapkit.protocols.link.inarp.InARP` ``('InARP',)``: under EtherType ``0x0806``, operation 8 parses as ARP with alias ``InARP``. Only :class:`~pcapkit.protocols.application.rarp.RARP` ``('RARP', 'DRARP')`` is bound to EtherType ``0x8035`` @@ -241,6 +241,5 @@ holds :class:`~pcapkit.protocols.link.linux_sll1.LinuxSLL1`. **The** ``schema/`` name, and sub-structure classes such as :class:`~pcapkit.protocols.schema.internet.igmpv3.Query` share its module. Ruled on :issue:`2529`, where the classes that do not match yet are pending: -:class:`arp.InARP `, :class:`tls.SSLv3 ` and :class:`null.NoPayload `. diff --git a/docs/source/ext.rst b/docs/source/ext.rst index c77920ca5e..7ca3180e15 100644 --- a/docs/source/ext.rst +++ b/docs/source/ext.rst @@ -22,7 +22,7 @@ The protocol classes :mod:`pcapkit` ships: +==================================================================+================+==============+======================================================================+ | | | :class:`pcapkit.protocols.link.arp.ARP` | + + ARP Family +-----------------------+-------------------------------------------------------------+ -| | | :class:`pcapkit.protocols.link.arp.InARP` | +| | | :class:`pcapkit.protocols.link.inarp.InARP` | + Link Layer +----------------+-----------------------+-------------------------------------------------------------+ | (:class:`~pcapkit.protocols.link.link.Link` subclasses) | :class:`pcapkit.protocols.link.ethernet.Ethernet` | + +----------------+-----------------------+-------------------------------------------------------------+ diff --git a/docs/source/pcapkit/protocols/application/tls.rst b/docs/source/pcapkit/protocols/application/tls.rst index d5a22757ec..724da359e2 100644 --- a/docs/source/pcapkit/protocols/application/tls.rst +++ b/docs/source/pcapkit/protocols/application/tls.rst @@ -62,7 +62,7 @@ carries ``0x0303`` and reads ``TLS 1.2``; and a TLS 1.2 ``ClientHello`` sent at record version ``0x0301`` reads ``TLS 1.0``. :class:`~pcapkit.protocols.application.tls.SSLv3` is for explicit -construction only, mirroring :class:`~pcapkit.protocols.link.arp.InARP`: it +construction only, mirroring :class:`~pcapkit.protocols.link.inarp.InARP`: it narrows :meth:`~pcapkit.protocols.application.tls.SSLv3.id` to ``('SSLv3',)`` and inherits :meth:`~pcapkit.protocols.application.tls.TLS.read` unchanged, so the alias still follows the wire. Dispatch never constructs one. diff --git a/docs/source/pcapkit/protocols/index.rst b/docs/source/pcapkit/protocols/index.rst index 080bb356eb..506fa6a8d5 100644 --- a/docs/source/pcapkit/protocols/index.rst +++ b/docs/source/pcapkit/protocols/index.rst @@ -141,7 +141,7 @@ from given information. The class hierarchy of :mod:`pcapkit.protocols`: click C_Tag "link/c_tag.html#pcapkit.protocols.link.c_tag.C_Tag" click S_Tag "link/s_tag.html#pcapkit.protocols.link.s_tag.S_Tag" click ARP "link/arp.html#pcapkit.protocols.link.arp.ARP" - click InARP "link/arp.html#pcapkit.protocols.link.arp.InARP" + click InARP "link/inarp.html#pcapkit.protocols.link.inarp.InARP" click Internet "internet/internet.html#pcapkit.protocols.internet.internet.Internet" click AH "internet/ah.html#pcapkit.protocols.internet.ah.AH" diff --git a/docs/source/pcapkit/protocols/link/arp.rst b/docs/source/pcapkit/protocols/link/arp.rst index 2ab51dcbd4..aabe50fb2c 100644 --- a/docs/source/pcapkit/protocols/link/arp.rst +++ b/docs/source/pcapkit/protocols/link/arp.rst @@ -1,13 +1,12 @@ -ARP/InARP - (Inverse) Address Resolution Protocol -================================================= +ARP - Address Resolution Protocol +================================= .. module:: pcapkit.protocols.link.arp :mod:`pcapkit.protocols.link.arp` contains -:class:`~pcapkit.protocols.link.arp.ARP` and -:class:`~pcapkit.protocols.link.arp.InARP`, -which implement extractors for (Inverse) Address Resolution -Protocol (ARP/InARP) [*]_, whose structure is described as +:class:`~pcapkit.protocols.link.arp.ARP` only, +which implements an extractor for Address Resolution +Protocol (ARP) [*]_, whose structure is described as below: .. table:: @@ -34,6 +33,12 @@ below: 24 192 ``arp.tpa`` Target Protocol Address ====== ==== ============= ======================= +.. versionremoved:: 1.6.0 + + ``pcapkit.protocols.link.arp.InARP``, with no alias. The class moved to + :mod:`pcapkit.protocols.link.inarp`, since a module holds one protocol + class, named after it (:issue:`2529`). + .. autoclass:: pcapkit.protocols.link.arp.ARP :no-members: :show-inheritance: @@ -59,12 +64,6 @@ below: .. automethod:: _make_addr_resolve .. automethod:: _make_proto_resolve -.. autoclass:: pcapkit.protocols.link.arp.InARP - :no-members: - :show-inheritance: - - .. automethod:: id - Header Schemas -------------- diff --git a/docs/source/pcapkit/protocols/link/inarp.rst b/docs/source/pcapkit/protocols/link/inarp.rst new file mode 100644 index 0000000000..b3689b7732 --- /dev/null +++ b/docs/source/pcapkit/protocols/link/inarp.rst @@ -0,0 +1,30 @@ +InARP - Inverse Address Resolution Protocol +=========================================== + +.. module:: pcapkit.protocols.link.inarp + +:mod:`pcapkit.protocols.link.inarp` contains +:class:`~pcapkit.protocols.link.inarp.InARP` only, +which implements an extractor for Inverse Address +Resolution Protocol (InARP) [*]_, whose frame is the one +:mod:`pcapkit.protocols.link.arp` describes. + +Nothing dispatches to :class:`~pcapkit.protocols.link.inarp.InARP`: +under EtherType ``0x0806``, an InARP operation parses as +:class:`~pcapkit.protocols.link.arp.ARP` with alias ``InARP``. + +.. versionadded:: 1.6.0 + + Moved here from :mod:`pcapkit.protocols.link.arp`, which keeps + :class:`~pcapkit.protocols.link.arp.ARP` alone, since a module holds one + protocol class, named after it (:issue:`2529`). + +.. autoclass:: pcapkit.protocols.link.inarp.InARP + :no-members: + :show-inheritance: + + .. automethod:: id + +.. rubric:: Footnotes + +.. [*] https://datatracker.ietf.org/doc/html/rfc2390 diff --git a/docs/source/pcapkit/protocols/link/index.rst b/docs/source/pcapkit/protocols/link/index.rst index 44afecf4d6..d091bb03b3 100644 --- a/docs/source/pcapkit/protocols/link/index.rst +++ b/docs/source/pcapkit/protocols/link/index.rst @@ -24,6 +24,7 @@ link layer, with detailed implementation and methods. link ethernet arp + inarp frad gre l2tp diff --git a/docs/source/pcapkit/protocols/link/link.rst b/docs/source/pcapkit/protocols/link/link.rst index 203f94efdd..9373433e6f 100644 --- a/docs/source/pcapkit/protocols/link/link.rst +++ b/docs/source/pcapkit/protocols/link/link.rst @@ -4,7 +4,8 @@ Link Layer Base Protocol .. module:: pcapkit.protocols.link.link :mod:`pcapkit.protocols.link.link` contains :class:`~pcapkit.protocols.link.link.Link`, -which is a base class for link layer protocols, e.g. :class:`~pcapkit.protocols.link.arp.ARP`/InARP, +which is a base class for link layer protocols, e.g. +:class:`~pcapkit.protocols.link.arp.ARP`/:class:`~pcapkit.protocols.link.inarp.InARP`, :class:`~pcapkit.protocols.link.ethernet.Ethernet`, :class:`~pcapkit.protocols.link.l2tp.L2TP` and :class:`~pcapkit.protocols.link.vlan.VLAN`. diff --git a/pcapkit/protocols/application/tls.py b/pcapkit/protocols/application/tls.py index 1aac70756a..fa02e86861 100644 --- a/pcapkit/protocols/application/tls.py +++ b/pcapkit/protocols/application/tls.py @@ -530,7 +530,7 @@ class SSLv3(TLS, schema=Schema_TLS, data=Data_TLS): """This class implements Secure Sockets Layer version 3. Dispatch never constructs it: an SSLv3 record parses as :class:`TLS` with - :attr:`~TLS.alias` ``'SSLv3'``. Like :class:`~pcapkit.protocols.link.arp.InARP` + :attr:`~TLS.alias` ``'SSLv3'``. Like :class:`~pcapkit.protocols.link.inarp.InARP` to :class:`~pcapkit.protocols.link.arp.ARP`, it narrows :meth:`id` only. """ diff --git a/pcapkit/protocols/link/__init__.py b/pcapkit/protocols/link/__init__.py index 1216774a82..5e4452ce43 100644 --- a/pcapkit/protocols/link/__init__.py +++ b/pcapkit/protocols/link/__init__.py @@ -15,7 +15,8 @@ from pcapkit.protocols.link.link import Link # Link Layer Protocols -from pcapkit.protocols.link.arp import ARP, InARP +from pcapkit.protocols.link.arp import ARP +from pcapkit.protocols.link.inarp import InARP from pcapkit.protocols.link.ethernet import Ethernet from pcapkit.protocols.link.frad import FRAD from pcapkit.protocols.link.gre import GRE diff --git a/pcapkit/protocols/link/arp.py b/pcapkit/protocols/link/arp.py index af4fa378a1..13735aa06e 100644 --- a/pcapkit/protocols/link/arp.py +++ b/pcapkit/protocols/link/arp.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- -"""ARP/InARP - (Inverse) Address Resolution Protocol -======================================================= +"""ARP - Address Resolution Protocol +======================================= .. module:: pcapkit.protocols.link.arp :mod:`pcapkit.protocols.link.arp` contains -:class:`~pcapkit.protocols.link.arp.ARP` and -:class:`~pcapkit.protocols.link.arp.InARP`, -which implement extractors for (Inverse) Address Resolution -Protocol (ARP/InARP) [*]_, whose structure is described as +:class:`~pcapkit.protocols.link.arp.ARP` only, +which implements an extractor for Address Resolution +Protocol (ARP) [*]_, whose structure is described as below: .. table:: @@ -37,6 +36,12 @@ .. [*] http://en.wikipedia.org/wiki/Address_Resolution_Protocol +.. versionremoved:: 1.6.0 + + ``pcapkit.protocols.link.arp.InARP``, with no alias. The class moved to + :mod:`pcapkit.protocols.link.inarp`, since a module holds one protocol + class, named after it (:issue:`2529`). + """ import ipaddress import re @@ -65,7 +70,7 @@ from pcapkit.protocols.protocol import ProtocolBase from pcapkit.protocols.schema.schema import Schema -__all__ = ['ARP', 'InARP'] +__all__ = ['ARP'] # Ethernet address pattern, of any number of octets (``hlen`` is not fixed at 6) PAT_MAC_ADDR = re.compile(rb'(?i)(?:[0-9a-f]{2}(?:[:-][0-9a-f]{2})*)?') @@ -78,7 +83,7 @@ class ARP(Link[Data_ARP, Schema_ARP], - Address Resolution Protocol (:class:`~pcapkit.protocols.link.arp.ARP`) [:rfc:`826`] - Reverse Address Resolution Protocol (:class:`~pcapkit.protocols.application.rarp.RARP`) [:rfc:`903`] - Dynamic Reverse Address Resolution Protocol (:class:`~pcapkit.protocols.application.drarp.DRARP`) [:rfc:`1931`] - - Inverse Address Resolution Protocol (:class:`~pcapkit.protocols.link.arp.InARP`) [:rfc:`2390`] + - Inverse Address Resolution Protocol (:class:`~pcapkit.protocols.link.inarp.InARP`) [:rfc:`2390`] .. versionchanged:: 1.5.0 @@ -516,23 +521,3 @@ def _make_proto_resolve(self, addr: 'IPv4Address | IPv6Address | str | bytes', p if isinstance(addr, (bytes, bytearray)): return bytes(addr) raise ProtocolError(f'{self.__class__.__name__}: invalid protocol address: {addr!r}') - - -class InARP(ARP, schema=Schema_ARP, data=Data_ARP): - """This class implements Inverse Address Resolution Protocol. - - .. versionchanged:: 1.5.0 - - Parses with the ARP schema rather than falling back to the raw one - (:issue:`1204`). - - """ - - ########################################################################## - # Methods. - ########################################################################## - - @classmethod - def id(cls) -> 'tuple[Literal["InARP"]]': # type: ignore[override] - """Index ID of the protocol.""" - return ('InARP',) diff --git a/pcapkit/protocols/link/inarp.py b/pcapkit/protocols/link/inarp.py new file mode 100644 index 0000000000..fa2f622da0 --- /dev/null +++ b/pcapkit/protocols/link/inarp.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +"""InARP - Inverse Address Resolution Protocol +================================================= + +.. module:: pcapkit.protocols.link.inarp + +:mod:`pcapkit.protocols.link.inarp` contains +:class:`~pcapkit.protocols.link.inarp.InARP` only, +which implements an extractor for Inverse Address +Resolution Protocol (InARP) [*]_, whose frame is the one +:mod:`pcapkit.protocols.link.arp` describes. + +Nothing dispatches to :class:`~pcapkit.protocols.link.inarp.InARP`: +under EtherType ``0x0806``, an InARP operation parses as +:class:`~pcapkit.protocols.link.arp.ARP` with alias ``InARP``. + +.. [*] https://datatracker.ietf.org/doc/html/rfc2390 + +.. versionadded:: 1.6.0 + + Moved here from :mod:`pcapkit.protocols.link.arp`, which keeps + :class:`~pcapkit.protocols.link.arp.ARP` alone, since a module holds one + protocol class, named after it (:issue:`2529`). + +""" +from typing import TYPE_CHECKING + +from pcapkit.protocols.data.link.arp import ARP as Data_ARP +from pcapkit.protocols.link.arp import ARP +from pcapkit.protocols.schema.link.arp import ARP as Schema_ARP + +if TYPE_CHECKING: + from typing_extensions import Literal + +__all__ = ['InARP'] + + +class InARP(ARP, schema=Schema_ARP, data=Data_ARP): + """This class implements Inverse Address Resolution Protocol. + + .. versionchanged:: 1.5.0 + + Parses with the ARP schema rather than falling back to the raw one + (:issue:`1204`). + + """ + + ########################################################################## + # Methods. + ########################################################################## + + @classmethod + def id(cls) -> 'tuple[Literal["InARP"]]': # type: ignore[override] + """Index ID of the protocol.""" + return ('InARP',) diff --git a/pcapkit/protocols/link/link.py b/pcapkit/protocols/link/link.py index 67956825c8..57d891f5d7 100644 --- a/pcapkit/protocols/link/link.py +++ b/pcapkit/protocols/link/link.py @@ -8,7 +8,7 @@ :mod:`pcapkit.protocols.link.link` contains :class:`~pcapkit.protocols.link.link.Link`, which is a base class for link layer protocols, e.g. -:class:`~pcapkit.protocols.link.arp.ARP`/:class:`~pcapkit.protocols.link.arp.InARP`, +:class:`~pcapkit.protocols.link.arp.ARP`/:class:`~pcapkit.protocols.link.inarp.InARP`, :class:`~pcapkit.protocols.link.ethernet.Ethernet`, :class:`~pcapkit.protocols.link.frad.FRAD`, :class:`~pcapkit.protocols.link.l2tp.L2TP`, diff --git a/tests/project/test_no_moved_name_re_exports_1744_unit.py b/tests/project/test_no_moved_name_re_exports_1744_unit.py index cca2ce0287..e60ea509b5 100644 --- a/tests/project/test_no_moved_name_re_exports_1744_unit.py +++ b/tests/project/test_no_moved_name_re_exports_1744_unit.py @@ -61,6 +61,7 @@ ('pcapkit.protocols.application.ngap', 'ProtocolIE'), ('pcapkit.protocols.internet.mh', 'NTPTimestamp'), ('pcapkit.protocols.internet.mh', 'PMIPv6Timestamp'), + ('pcapkit.protocols.link.arp', 'InARP'), # #2529: renamed after their modules. ('pcapkit.protocols.application.httpv1', 'HTTP'), ('pcapkit.protocols.application.httpv2', 'HTTP'), @@ -94,10 +95,13 @@ ('pcapkit.protocols.application.ftp', 'FTP_DATA', 'pcapkit/protocols/application/ftp.py', 'pcapkit/protocols/application/ftp.rst', '1.5.0'), - # #2529: shipped in 1.5.x, moved to its own module. + # #2529: shipped in 1.5.x, moved to their own modules. ('pcapkit.protocols.application.rarp', 'DRARP', 'pcapkit/protocols/application/rarp.py', 'pcapkit/protocols/application/rarp.rst', '1.6.0'), + ('pcapkit.protocols.link.arp', 'InARP', + 'pcapkit/protocols/link/arp.py', + 'pcapkit/protocols/link/arp.rst', '1.6.0'), # #2529: shipped in 1.5.x, renamed after their modules. ('pcapkit.protocols.application.httpv1', 'HTTP', 'pcapkit/protocols/application/httpv1.py', diff --git a/tests/protocols/application/test_layer_placement_unit.py b/tests/protocols/application/test_layer_placement_unit.py index d34f45142d..d85122f387 100644 --- a/tests/protocols/application/test_layer_placement_unit.py +++ b/tests/protocols/application/test_layer_placement_unit.py @@ -103,7 +103,8 @@ def test_ospf_and_rarp_report_the_application_layer(self) -> None: def test_arp_and_inarp_stay_on_the_link_layer(self) -> None: """:rfc:`1122#section-2.3.2` keeps ARP on the link layer; RARP is not.""" - from pcapkit.protocols.link.arp import ARP, InARP + from pcapkit.protocols.link.arp import ARP + from pcapkit.protocols.link.inarp import InARP self.assertEqual(ARP.__layer__, 'Link') self.assertEqual(InARP.__layer__, 'Link') diff --git a/tests/protocols/application/test_ssl_tls_dtls_unit.py b/tests/protocols/application/test_ssl_tls_dtls_unit.py index 0ef883dcae..b12e5f57e2 100644 --- a/tests/protocols/application/test_ssl_tls_dtls_unit.py +++ b/tests/protocols/application/test_ssl_tls_dtls_unit.py @@ -792,7 +792,7 @@ def test_dtls_0xfeff_client_hello_negotiating_1_3_dispatches_dtls_1_3(self) -> N def test_sslv3_is_constructible_directly_and_narrows_id(self) -> None: """:class:`SSLv3` -- explicit/manual construction only, mirroring - :class:`~pcapkit.protocols.link.arp.InARP`'s relationship to + :class:`~pcapkit.protocols.link.inarp.InARP`'s relationship to :class:`~pcapkit.protocols.link.arp.ARP`: it narrows :meth:`id` only and inherits :meth:`~pcapkit.protocols.application.tls.TLS.read` unchanged, so parsing SSLv3-shaped data through it sets @@ -809,7 +809,7 @@ def test_sslv3_is_constructible_directly_and_narrows_id(self) -> None: self.assertEqual(SSLv3.id(), ('SSLv3',)) def test_sslv3_class_does_not_force_its_own_alias(self) -> None: - """The same nuance :class:`~pcapkit.protocols.link.arp.InARP` has: + """The same nuance :class:`~pcapkit.protocols.link.inarp.InARP` has: constructing :class:`SSLv3` directly over data that is not actually SSLv3-shaped still reports the *real* tier, since :meth:`read` is inherited unmodified and dispatches off the wire, not off the class diff --git a/tests/protocols/link/test_arp_roundtrip_unit.py b/tests/protocols/link/test_arp_roundtrip_unit.py index a80562fb5c..cd7b7e98d1 100644 --- a/tests/protocols/link/test_arp_roundtrip_unit.py +++ b/tests/protocols/link/test_arp_roundtrip_unit.py @@ -3,7 +3,7 @@ GitHub issues: -* #1204: :class:`~pcapkit.protocols.link.arp.InARP` and +* #1204: :class:`~pcapkit.protocols.link.inarp.InARP` and :class:`~pcapkit.protocols.application.drarp.DRARP` did not pass ``schema=``/``data=``, so they fell back to the ``Raw`` schema and could not parse any input. @@ -34,7 +34,7 @@ #: ``(module, class)`` for every ARP-family class. CLASSES = ( ('pcapkit.protocols.link.arp', 'ARP'), - ('pcapkit.protocols.link.arp', 'InARP'), + ('pcapkit.protocols.link.inarp', 'InARP'), ('pcapkit.protocols.application.rarp', 'RARP'), ('pcapkit.protocols.application.drarp', 'DRARP'), ) @@ -72,7 +72,7 @@ def test_subclasses_use_arp_schema(self) -> None: def test_subclasses_round_trip(self) -> None: """#1204: the issue's repro parses and rebuilds for InARP and DRARP.""" - for module, name, oper in (('pcapkit.protocols.link.arp', 'InARP', '0008'), + for module, name, oper in (('pcapkit.protocols.link.inarp', 'InARP', '0008'), ('pcapkit.protocols.application.drarp', 'DRARP', '0005')): with self.subTest(cls=name): cls = self._cls(module, name) diff --git a/tests/protocols/link/test_inarp_unit.py b/tests/protocols/link/test_inarp_unit.py new file mode 100644 index 0000000000..99444daf23 --- /dev/null +++ b/tests/protocols/link/test_inarp_unit.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +"""Unit tests for :mod:`pcapkit.protocols.link.inarp`. + +#2529: a module holds one protocol class, named after it, so ``InARP`` left +:mod:`pcapkit.protocols.link.arp` for a module of its own, with no re-export at +the old path. Every case builds its own octets. + +""" +from __future__ import annotations + +import importlib +import importlib.util +import unittest + +from tests._support import reimport_once_per_class + +RUNTIME_DEPS = ('tbtrim', 'aenum', 'chardet', 'dictdumper') +HAS_RUNTIME = all(importlib.util.find_spec(name) is not None for name in RUNTIME_DEPS) + +#: An InARP-Request (operation 8) over Ethernet and IPv4, :rfc:`2390`. +INARP_REQUEST = bytes.fromhex('000108000604' '0008' '001122334455' '0a000001' + '66778899aabb' '00000000') + + +@unittest.skipUnless(HAS_RUNTIME, 'runtime dependencies not installed') +class InARPModuleTests(unittest.TestCase): + """``InARP`` lives in its own module and keeps ARP's behaviour.""" + + def setUp(self) -> None: + reimport_once_per_class(self) + + def test_inarp_is_defined_in_its_own_module(self) -> None: + from pcapkit.protocols.link.arp import ARP + from pcapkit.protocols.link.inarp import InARP + + inarp = importlib.import_module('pcapkit.protocols.link.inarp') + self.assertEqual(InARP.__module__, 'pcapkit.protocols.link.inarp') + self.assertEqual(inarp.__all__, ['InARP']) + self.assertEqual(InARP.__bases__, (ARP,)) + + def test_arp_module_holds_arp_alone(self) -> None: + """#2529: no re-export at the old path (#1715, #1744).""" + arp = importlib.import_module('pcapkit.protocols.link.arp') + + self.assertEqual(arp.__all__, ['ARP']) + self.assertFalse(hasattr(arp, 'InARP')) + + def test_id_index_and_layer(self) -> None: + """``InARP`` narrows ``id()`` to itself and inherits ARP's ``__index__``.""" + from pcapkit.const.reg.ethertype import EtherType + from pcapkit.protocols.link.arp import ARP + from pcapkit.protocols.link.inarp import InARP + + self.assertEqual(InARP.id(), ('InARP',)) + self.assertEqual(ARP.id(), ('ARP',)) + self.assertNotIn('__index__', vars(InARP)) + self.assertEqual(InARP.__index__(), EtherType.Address_Resolution_Protocol) + self.assertEqual(InARP.__layer__, 'Link') + + def test_top_level_names_are_the_new_homes_object(self) -> None: + import pcapkit + import pcapkit.protocols + import pcapkit.protocols.link + from pcapkit.protocols.link.inarp import InARP + + for package in (pcapkit, pcapkit.protocols, pcapkit.protocols.link): + with self.subTest(package=package.__name__): + self.assertIs(package.InARP, InARP) + self.assertIn('InARP', package.__all__) + + def test_parsed_arp_keeps_its_dynamic_inarp_alias(self) -> None: + """EtherType ``0x0806`` binds ARP alone; operation 8 reports ``InARP``.""" + from pcapkit.protocols.link.arp import ARP + from pcapkit.protocols.link.inarp import InARP + + parsed = ARP(INARP_REQUEST) + self.assertIs(type(parsed), ARP) + self.assertEqual(parsed.alias, 'InARP') + self.assertEqual(parsed.name, 'Inverse Address Resolution Protocol') + self.assertEqual(InARP(INARP_REQUEST).alias, 'InARP') + self.assertEqual(InARP.from_data(InARP(INARP_REQUEST).info).data, INARP_REQUEST) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/protocols/link/test_link_unit.py b/tests/protocols/link/test_link_unit.py index fa3b8be2ec..1bc74caac7 100644 --- a/tests/protocols/link/test_link_unit.py +++ b/tests/protocols/link/test_link_unit.py @@ -135,7 +135,8 @@ def test_ethernet_index_and_length_hint_are_stable(self) -> None: def test_arp_id_index_and_length_hint_are_stable(self) -> None: from pcapkit.const.reg.ethertype import EtherType - from pcapkit.protocols.link.arp import ARP, InARP + from pcapkit.protocols.link.arp import ARP + from pcapkit.protocols.link.inarp import InARP proto = object.__new__(ARP)