From 6bf931d898d27e3f2b02b4480e089114addb5ccd Mon Sep 17 00:00:00 2001 From: Sebastian Majewski Date: Sun, 8 Sep 2024 19:46:57 -0500 Subject: [PATCH] Working on DHCPv4 options --- .../options/dhcp4_option__message_type.py | 6 +- .../test__dhcp4__option__message_type.py | 258 ++++++++++++++---- 2 files changed, 210 insertions(+), 54 deletions(-) diff --git a/pytcp/protocols/dhcp4/options/dhcp4_option__message_type.py b/pytcp/protocols/dhcp4/options/dhcp4_option__message_type.py index 88a3ba9d..846536a7 100644 --- a/pytcp/protocols/dhcp4/options/dhcp4_option__message_type.py +++ b/pytcp/protocols/dhcp4/options/dhcp4_option__message_type.py @@ -54,7 +54,7 @@ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -DHCP4__OPTION__MESSAGE_TYPE__LEN = 4 +DHCP4__OPTION__MESSAGE_TYPE__LEN = 3 DHCP4__OPTION__MESSAGE_TYPE__STRUCT = "! BB B" @@ -124,7 +124,7 @@ def _validate_integrity(_bytes: bytes, /) -> None: if (value := _bytes[1]) > len(_bytes): raise Dhcp4IntegrityError( "The DHCPv4 Message Type option length must be less than or equal " - "to the length of provided bytes ({len(_bytes)}). Got: {value!r}" + f"to the length of provided bytes ({len(_bytes)}). Got: {value!r}" ) @override @@ -146,4 +146,4 @@ def from_bytes(_bytes: bytes, /) -> Dhcp4OptionMessageType: Dhcp4OptionMessageType._validate_integrity(_bytes) - return Dhcp4OptionMessageType(Dhcp4MessageType.from_int(_bytes[3])) + return Dhcp4OptionMessageType(Dhcp4MessageType.from_int(_bytes[2])) diff --git a/tests/unit/protocols/dhcp4/test__dhcp4__option__message_type.py b/tests/unit/protocols/dhcp4/test__dhcp4__option__message_type.py index cafba344..4281692b 100644 --- a/tests/unit/protocols/dhcp4/test__dhcp4__option__message_type.py +++ b/tests/unit/protocols/dhcp4/test__dhcp4__option__message_type.py @@ -32,18 +32,18 @@ ver 3.0.2 """ -''' + from typing import Any from parameterized import parameterized_class # type: ignore from testslide import TestCase -from pytcp.lib.int_checks import UINT_8__MIN +from pytcp.protocols.dhcp4.dhcp4__enums import Dhcp4MessageType +from pytcp.protocols.dhcp4.dhcp4__errors import Dhcp4IntegrityError from pytcp.protocols.dhcp4.options.dhcp4_option import Dhcp4OptionType from pytcp.protocols.dhcp4.options.dhcp4_option__message_type import ( Dhcp4OptionMessageType, ) -from pytcp.protocols.dhcp4.dhcp4__errors import Dhcp4IntegrityError class TestDhcp4OptionMessageTypeAsserts(TestCase): @@ -56,9 +56,8 @@ def setUp(self) -> None: Create the default arguments for the DHCPv4 Message Type option constructor. """ - self._option_kwargs = { - "message_type": Dhcp4OptionType.MESSAGE_TYPE, - } + self._args: list[Any] = [Dhcp4MessageType.DISCOVER] + self._kwargs: dict[str, Any] = {} def test__dhcp4__option__message_type__message_type__not_Dhcp4MessageType( self, @@ -68,31 +67,129 @@ def test__dhcp4__option__message_type__message_type__not_Dhcp4MessageType( provided 'message_type' argument is not a Dhcp4MessageType. """ - self._option_kwargs["message_type"] = value = "not an Dhcp4MessageType" # type: ignore + self._args[0] = value = "not an Dhcp4MessageType" with self.assertRaises(AssertionError) as error: - Dhcp4OptionMessageType(**self._option_kwargs) # type: ignore + Dhcp4OptionMessageType(*self._args, **self._kwargs) self.assertEqual( str(error.exception), - f"The 'message_type' field must be a Dhcp4MEssageType. Got: {type(value)!r}", + f"The 'message_type' field must be a Dhcp4MessageType. Got: {type(value)!r}", ) @parameterized_class( [ { - "_description": "The DHCPv4 Message Type option.", - "_args": [], - "_kwargs": { - "message_type": Dhcp4OptionType.MESSAGE_TYPE, + "_description": "The DHCPv4 Message Type option (discover).", + "_args": [Dhcp4MessageType.DISCOVER], + "_kwargs": {}, + "_results": { + "__len__": 3, + "__str__": "message_type Discover", + "__repr__": ( + "Dhcp4OptionMessageType(message_type=)" + ), + "__bytes__": b"\x35\x03\x01", + "message_type": Dhcp4MessageType.DISCOVER, + }, + }, + { + "_description": "The DHCPv4 Message Type option (offer).", + "_args": [Dhcp4MessageType.OFFER], + "_kwargs": {}, + "_results": { + "__len__": 3, + "__str__": "message_type Offer", + "__repr__": ( + "Dhcp4OptionMessageType(message_type=)" + ), + "__bytes__": b"\x35\x03\x02", + "message_type": Dhcp4MessageType.OFFER, + }, + }, + { + "_description": "The DHCPv4 Message Type option (request).", + "_args": [Dhcp4MessageType.REQUEST], + "_kwargs": {}, + "_results": { + "__len__": 3, + "__str__": "message_type Request", + "__repr__": ( + "Dhcp4OptionMessageType(message_type=)" + ), + "__bytes__": b"\x35\x03\x03", + "message_type": Dhcp4MessageType.REQUEST, + }, + }, + { + "_description": "The DHCPv4 Message Type option (decline).", + "_args": [Dhcp4MessageType.DECLINE], + "_kwargs": {}, + "_results": { + "__len__": 3, + "__str__": "message_type Decline", + "__repr__": ( + "Dhcp4OptionMessageType(message_type=)" + ), + "__bytes__": b"\x35\x03\x04", + "message_type": Dhcp4MessageType.DECLINE, + }, + }, + { + "_description": "The DHCPv4 Message Type option (ack).", + "_args": [Dhcp4MessageType.ACK], + "_kwargs": {}, + "_results": { + "__len__": 3, + "__str__": "message_type Ack", + "__repr__": ( + "Dhcp4OptionMessageType(message_type=)" + ), + "__bytes__": b"\x35\x03\x05", + "message_type": Dhcp4MessageType.ACK, + }, + }, + { + "_description": "The DHCPv4 Message Type option (nak).", + "_args": [Dhcp4MessageType.NAK], + "_kwargs": {}, + "_results": { + "__len__": 3, + "__str__": "message_type Nak", + "__repr__": ( + "Dhcp4OptionMessageType(message_type=)" + ), + "__bytes__": b"\x35\x03\x06", + "message_type": Dhcp4MessageType.NAK, + }, + }, + { + "_description": "The DHCPv4 Message Type option (release).", + "_args": [Dhcp4MessageType.RELEASE], + "_kwargs": {}, + "_results": { + "__len__": 3, + "__str__": "message_type Release", + "__repr__": ( + "Dhcp4OptionMessageType(message_type=)" + ), + "__bytes__": b"\x35\x03\x07", + "message_type": Dhcp4MessageType.RELEASE, }, + }, + { + "_description": "The DHCPv4 Message Type option (inform).", + "_args": [Dhcp4MessageType.INFORM], + "_kwargs": {}, "_results": { "__len__": 3, - "__str__": "message_type ", - "__repr__": "Dhcp4OptionMessageType(wscale=14)", - "__bytes__": b"\x03\x03\x0e", - "wscale": 14, + "__str__": "message_type Inform", + "__repr__": ( + "Dhcp4OptionMessageType(message_type=)" + ), + "__bytes__": b"\x35\x03\x08", + "message_type": Dhcp4MessageType.INFORM, }, }, ] @@ -103,7 +200,8 @@ class TestDhcp4OptionMessageTypeAssembler(TestCase): """ _description: str - _args: dict[str, Any] + _args: list[Any] + _kwargs: dict[str, Any] _results: dict[str, Any] def setUp(self) -> None: @@ -111,7 +209,7 @@ def setUp(self) -> None: Initialize the DHCPv4 Message Type option object with testcase arguments. """ - self._option = Dhcp4OptionMessageType(**self._args) + self._option = Dhcp4OptionMessageType(*self._args, **self._kwargs) def test__dhcp4__option__message_type__len(self) -> None: """ @@ -157,42 +255,104 @@ def test__dhcp4__option__message_type__bytes(self) -> None: self._results["__bytes__"], ) - def test__dhcp4__option__message_type__wscale(self) -> None: + def test__dhcp4__option__message_type__mesage_type(self) -> None: """ - Ensure the DHCPv4 Message Type option 'wscale' field contains a correct value. + Ensure the DHCPv4 Message Type option 'message_type' field contains a correct + value. """ self.assertEqual( - self._option.wscale, - self._results["wscale"], + self._option.message_type, + self._results["message_type"], ) @parameterized_class( [ { - "_description": "The DHCPv4 Message Type option.", - "_args": { - "bytes": b"\x03\x03\x0e", + "_description": "The DHCPv4 Message Type option (discover).", + "_args": [b"\x35\x03\x01" + b"ZH0PA"], + "_kwargs": {}, + "_results": { + "option": Dhcp4OptionMessageType( + message_type=Dhcp4MessageType.DISCOVER + ), }, + }, + { + "_description": "The DHCPv4 Message Type option (offer).", + "_args": [b"\x35\x03\x02" + b"ZH0PA"], + "_kwargs": {}, "_results": { - "option": Dhcp4OptionMessageType(wscale=14), + "option": Dhcp4OptionMessageType( + message_type=Dhcp4MessageType.OFFER + ), }, }, { - "_description": "The DHCPv4 Message Type option (maximum value correction).", - "_args": { - "bytes": b"\x03\x03\xff", + "_description": "The DHCPv4 Message Type option (request).", + "_args": [b"\x35\x03\x03" + b"ZH0PA"], + "_kwargs": {}, + "_results": { + "option": Dhcp4OptionMessageType( + message_type=Dhcp4MessageType.REQUEST + ), }, + }, + { + "_description": "The DHCPv4 Message Type option (decline).", + "_args": [b"\x35\x03\x04" + b"ZH0PA"], + "_kwargs": {}, "_results": { - "option": Dhcp4OptionMessageType(wscale=14), + "option": Dhcp4OptionMessageType( + message_type=Dhcp4MessageType.DECLINE + ), }, }, { - "_description": "The DHCPv4 Message Type option minimum length assert.", - "_args": { - "bytes": b"\x03", + "_description": "The DHCPv4 Message Type option (ack).", + "_args": [b"\x35\x03\x05" + b"ZH0PA"], + "_kwargs": {}, + "_results": { + "option": Dhcp4OptionMessageType( + message_type=Dhcp4MessageType.ACK + ), + }, + }, + { + "_description": "The DHCPv4 Message Type option (nak).", + "_args": [b"\x35\x03\x06" + b"ZH0PA"], + "_kwargs": {}, + "_results": { + "option": Dhcp4OptionMessageType( + message_type=Dhcp4MessageType.NAK + ), + }, + }, + { + "_description": "The DHCPv4 Message Type option (release).", + "_args": [b"\x35\x03\x07" + b"ZH0PA"], + "_kwargs": {}, + "_results": { + "option": Dhcp4OptionMessageType( + message_type=Dhcp4MessageType.RELEASE + ), + }, + }, + { + "_description": "The DHCPv4 Message Type option (inform).", + "_args": [b"\x35\x03\x08" + b"ZH0PA"], + "_kwargs": {}, + "_results": { + "option": Dhcp4OptionMessageType( + message_type=Dhcp4MessageType.INFORM + ), }, + }, + { + "_description": "The DHCPv4 Message Type option minimum length assert.", + "_args": [b"\x35"], + "_kwargs": {}, "_results": { "error": AssertionError, "error_message": ( @@ -203,22 +363,20 @@ def test__dhcp4__option__message_type__wscale(self) -> None: }, { "_description": "The DHCPv4 Message Type option incorrect 'type' field assert.", - "_args": { - "bytes": b"\xff\03\x0e", - }, + "_args": [b"\xfe\03\x01"], + "_kwargs": {}, "_results": { "error": AssertionError, "error_message": ( - f"The DHCPv4 Message Type option type must be {Dhcp4OptionType.WSCALE!r}. " - f"Got: {Dhcp4OptionType.from_int(255)!r}" + f"The DHCPv4 Message Type option type must be {Dhcp4OptionType.MESSAGE_TYPE!r}. " + f"Got: {Dhcp4OptionType.from_int(254)!r}" ), }, }, { "_description": "The DHCPv4 Message Type option length integrity check (I).", - "_args": { - "bytes": b"\x03\02\x0e", - }, + "_args": [b"\x35\02\x01"], + "_kwargs": {}, "_results": { "error": Dhcp4IntegrityError, "error_message": ( @@ -229,15 +387,13 @@ def test__dhcp4__option__message_type__wscale(self) -> None: }, { "_description": "The DHCPv4 Message Type option length integrity check (II).", - "_args": { - "bytes": b"\x03\03", - }, + "_args": [b"\x35\03"], + "_kwargs": {}, "_results": { "error": Dhcp4IntegrityError, "error_message": ( "[INTEGRITY ERROR][DHCPv4] The DHCPv4 Message Type option length must " - "be less than or equal to the length of provided bytes " - "(2). Got: 3" + "be less than or equal to the length of provided bytes (2). Got: 3" ), }, }, @@ -249,7 +405,8 @@ class TestDhcp4OptionMessageTypeParser(TestCase): """ _description: str - _args: dict[str, Any] + _args: list[Any] + _kwargs: dict[str, Any] _results: dict[str, Any] def test__dhcp4__option__message_type__from_bytes(self) -> None: @@ -260,7 +417,7 @@ def test__dhcp4__option__message_type__from_bytes(self) -> None: if "option" in self._results: option = Dhcp4OptionMessageType.from_bytes( - self._args["bytes"] + b"ZH0PA" + *self._args, **self._kwargs ) self.assertEqual( @@ -270,10 +427,9 @@ def test__dhcp4__option__message_type__from_bytes(self) -> None: if "error" in self._results: with self.assertRaises(self._results["error"]) as error: - Dhcp4OptionMessageType.from_bytes(self._args["bytes"]) + Dhcp4OptionMessageType.from_bytes(*self._args, **self._kwargs) self.assertEqual( str(error.exception), self._results["error_message"], ) -'''