Example #1
0
 def test_address_space_cannot_describe_net_if_no_previous_supernet(self):
     """A network can only be described if a supernet exists."""
     address_space = AddressSpace(strict_=True)
     for data in (
         ("203.0.113.0/24", "an IPv4 test net"),
         ("2000::/3", "Current loose global IPv6 network"),
         ("192.0.2.0/24", "another IPv4 test net"),
         ("fe80::/64", "IPv6 link-local network"),
         ("10.123.0.0/16", "A private IPv4 address"),
         ("2001:db8:ab00::/40", "An IPv6 network in doc range"),
     ):
         with self.subTest(data=data):
             no_previous_supernet = False
             try:
                 address_space.describe(
                     ip_parameter=data[0],
                     description=data[1],
                 )
             except StrictSupernetError:
                 no_previous_supernet = True
             self.assertTrue(
                 no_previous_supernet,
                 "If strict address space, can describe networks only "
                 "if supernet already exists",
             )
Example #2
0
 def test_address_space_cannot_describe_address_if_no_previous_net(self):
     """An address can only be described if a supernet exists."""
     address_space = AddressSpace(strict_=True)
     for data in (
         ("203.0.113.128", "a IPv4 test net address"),
         ("2000::", "A 6 characts short IPv6 address"),
         ("192.0.2.192", "another IPv4 test net address"),
         ("fe80::abcd", "an IPv6 link-local address"),
         ("10.123.45.67", "A private IPv4 address"),
         ("2001:db8:abcd::1234", "An IPv6 address in doc range"),
     ):
         with self.subTest(data=data):
             no_previous_supernet = False
             try:
                 address_space.describe(
                     ip_parameter=data[0],
                     description=data[1],
                 )
             except StrictSupernetError:
                 no_previous_supernet = True
             self.assertTrue(
                 no_previous_supernet,
                 "If strict address space, can describe address only "
                 "if supernet already exists",
             )
Example #3
0
 def test_delegated_network_cannot_describe_subnet_as_new(self):
     """Inserting delegation with present supernet must raise exception."""
     for strict in (False, True):
         with self.subTest(strict=strict):
             address_space = AddressSpace(strict_=strict)
             for data in (
                 ("2001:db8::/32", "2001:db8::/48"),
                 ("203.0.113.0/24", "203.0.113.0/27"),
                 ("fdab:cdef:1234::/48", "fdab:cdef:1234:5678::/64"),
                 ("192.0.2.0/24", "192.0.2.128/26"),
                 ("::/0", "::ab00/126"),
                 ("0.0.0.0/0", "10.0.0.0/8"),
             ):
                 with self.subTest(data=data):
                     self.assertTrue(
                         address_space.describe_new_delegated_network(
                             network_parameter=data[0],
                             description="actual delegation",
                         ),
                         "Describe a network without a previous inserted "
                         "supernet",
                     )
                     supernet_detected = False
                     try:
                         address_space.describe_new_delegated_network(
                             network_parameter=data[1],
                             description="trying subnet as delegated",
                         )
                     except StrictSupernetError:
                         supernet_detected = True
                     self.assertTrue(
                         supernet_detected,
                         "If inserting delegated network, no supernet "
                         "should be present, for strict and non strict "
                         "address spaces")
Example #4
0
 def test_address_space_strict_cannot_be_assigned_to(self):
     """AddressSpace's strict member cannot be assigned."""
     address_space = AddressSpace()
     cannot_be_assigned = False
     try:
         address_space.strict = False
     except AttributeError:
         cannot_be_assigned = True
     self.assertTrue(
         cannot_be_assigned,
         "AddressSpace instance' strict cannot be assigned",
     )
Example #5
0
 def test_delegated_network_no_empty_arguments(self):
     """New delegated network method with no empty argument list."""
     for strict in (False, True):
         with self.subTest(strict=strict):
             address_space = AddressSpace(strict_=strict)
             no_empty_arguments = False
             try:
                 address_space.describe_new_delegated_network()
             except TypeError:
                 no_empty_arguments = True
             self.assertTrue(
                 no_empty_arguments,
                 "Empty arguments should not be accepted in "
                 "describe_new_delegated_network",
             )
Example #6
0
 def test_delegated_network_keyword_only_no_positional_args(self):
     """New delegated network must use keyword-only args."""
     for strict in (False, True):
         with self.subTest(strict=strict):
             address_space = AddressSpace(strict_=strict)
             no_positional_arguments = False
             try:
                 address_space.describe_new_delegated_network(
                     "2001:db8::/32", "IPv6 documentation network space")
             except TypeError:
                 no_positional_arguments = True
             self.assertTrue(
                 no_positional_arguments,
                 "No positional argument should be accepted in "
                 "describe_new_delegated_network",
             )
Example #7
0
 def test_address_space_strict(self):
     """Retrieve AddressSpace's strict member."""
     address_space = AddressSpace()
     self.assertIsInstance(
         address_space.strict, bool,
         "AddressSpace instance expected to have "
         "a strict boolean member")
Example #8
0
 def test_address_space_default_strict_should_be_true(self):
     """Default value for AddressSpace's strict member should be True."""
     address_space = AddressSpace()
     self.assertIs(
         address_space.strict,
         True,
         "AddressSpace's default strict value expected to be True.",
     )
Example #9
0
 def test_address_space_init_cannot_accept_positional_arguments(self):
     """init method as keyword only, without positional parameters."""
     no_positional_arguments = False
     try:
         AddressSpace(False)
     except TypeError:
         no_positional_arguments = True
     self.assertTrue(
         no_positional_arguments,
         "No positional argument should be accepted in __init__",
     )
Example #10
0
 def test_delegated_network_cannot_insert_same_as_new(self):
     """Inserting delegation with same net must raise exception."""
     for net in (
             "2001:db8::/32",
             "2001:db8::/48",
             "203.0.113.0/24",
             "203.0.113.0/27",
             "fdab:cdef:1234::/48",
             "fdab:cdef:1234:5678::/64",
             "192.0.2.0/24",
             "192.0.2.128/26",
             "::/0",
             "::ab00/126",
             "0.0.0.0/0",
             "10.0.0.0/8",
     ):
         with self.subTest(net=net):
             for strict in (False, True):
                 with self.subTest(strict=strict):
                     address_space = AddressSpace(strict_=strict)
                     self.assertTrue(
                         address_space.describe_new_delegated_network(
                             network_parameter=net,
                             description="actual delegation",
                         ),
                         "Describe a network without a previous inserted "
                         "supernet",
                     )
                     same_net = False
                     try:
                         address_space.describe_new_delegated_network(
                             network_parameter=net,
                             description="trying to insert same as new",
                         )
                     except SameDelegationAsNewError:
                         same_net = True
                     self.assertTrue(
                         same_net,
                         "Cannot insert same delegation as new more than "
                         "once",
                     )
Example #11
0
class AddressSpace_default_export_TestCase(unittest.TestCase):
    """Tests related to AddressSpace's data export."""
    def setUp(self):
        self.address_space = AddressSpace()
        self.exported_data = self.address_space.export_data()

    def test_address_space_export_for_default_instance(self):
        """Default instance should evaluate to True."""
        self.assertTrue(self.exported_data,
                        "exported data should truth evaluate to True")

    def test_address_space_export_for_default_instance_should_be_dict(self):
        """Default instance should return dict with default values."""
        self.assertIsInstance(self.exported_data, dict,
                              "exported data should be a dict")

    def test_address_space_export_for_default_instance_should_have_keys(self):
        """Default instance should return dict with keys."""
        for key in ("description", "nested_ip_objects"):
            with self.subTest(key=key):
                self.assertIn(key, self.exported_data,
                              "exported data should have specific key")

    def test_address_space_export_for_default_instance_exact_keys(self):
        """Default instance should return dict with keys."""
        keys = set({"description", "nested_ip_objects"})
        self.assertEqual(keys, set(self.exported_data),
                         "exported data should have exactly required keys")

    def test_address_space_export_for_default_instance_values(self):
        """Default instance export data dict should have two dicts."""
        for key in ("description", "nested_ip_objects"):
            with self.subTest(key=key):
                self.assertIsInstance(self.exported_data[key], dict,
                                      "exported data dict should have dicts")

    def test_address_space_export_description_should_be_the_same(self):
        """Exported description should be the same as instance's."""
        self.assertEqual(
            self.exported_data["description"],
            self.address_space._AddressSpace__description,
            "Exported description should be the same as instance's.",
        )

    def test_address_space_export_nested_ip_objects_keys(self):
        """Nested IP object keys validation."""
        self.assertEqual(
            set(self.exported_data["nested_ip_objects"]),
            set(self.address_space._AddressSpace__networks).union(
                set(self.address_space._AddressSpace__addresses)),
            "Exported nested IP object should have the same keys as "
            "union of networks and address keys.")
Example #12
0
 def test_delegated_network_into_address_space(self):
     """Inserts a network without supernet present in address space."""
     for strict in (False, True):
         with self.subTest(strict_=strict):
             address_space = AddressSpace(strict_=strict)
             for data in (
                 ("2001:db8::/32", "IPv6 documentation network space"),
                 ("203.0.113.0/24", "one of IPv4 test net"),
                 ("fdab:cdef:1234::/48", "an IPv6 unique-local net"),
                 ("192.0.2.0/24", "another IPv4 test net"),
                 ("::/0", "whole IPv6 address space"),
                 ("0.0.0.0/0", "whole IPv4 address space"),
             ):
                 with self.subTest(data=data):
                     self.assertTrue(
                         address_space.describe_new_delegated_network(
                             network_parameter=data[0],
                             description=data[1],
                         ),
                         "Describe a network without a previous inserted "
                         "supernet",
                     )
Example #13
0
class AddressSpace_description_TestCase(unittest.TestCase):
    """Tests for description related methods."""
    def setUp(self):
        """Set up test fixtures with new AddressSpace."""
        self.address_space = AddressSpace(strict_=False)

    def test_address_space_as_AddressSpace(self):
        """Validate if address_space is instance of AddressSpace."""
        self.assertIsInstance(self.address_space, AddressSpace)

    def test_describe_no_empty_arguments(self):
        """describe method with no empty argument list."""
        no_empty_arguments = False
        try:
            self.address_space.describe()
        except TypeError:
            no_empty_arguments = True
        self.assertTrue(
            no_empty_arguments,
            "Empty arguments should not be accepted in describe",
        )

    def test_describe_keyword_only_no_positional_arguments(self):
        """describe method as keyword only, without positional parameters."""
        no_positional_arguments = False
        try:
            self.address_space.describe("203.0.113.128", "test net address")
        except TypeError:
            no_positional_arguments = True
        self.assertTrue(
            no_positional_arguments,
            "No positional argument should be accepted in describe",
        )

    def test_describe_address(self):
        """Add valid IP address with non-empty str description."""
        for parameters in (
            ("123.123.123.123", "123 is nice"),
            ("203.0.113.129", "Second subnet gateway"),
            ("192.0.2.123", "123 is nice, test net"),
            ("2001:db8::abcd:ef12", "ipv6 doc address"),
            ("2000::", "first global address for now"),
            ("fe80::", "even link-local?"),
        ):
            with self.subTest(parameters=parameters):
                self.assertIs(
                    self.address_space.describe(ip_parameter=parameters[0],
                                                description=parameters[1]),
                    True,
                )

    def test_describe_network(self):
        """Add valid IP network with non-empty str description."""
        for parameters in (
            ("10.0.0.0/16", "a private IPv4 network"),
            ("203.0.113.128/25", "part of a test net"),
            ("0.0.0.0/0", "whole IPv4 address space as network"),
            ("2001:db8:1234:5678::/64", "a documentation IPv6 network"),
            ("fe80::/64", "IPv6 link-local network"),
            ("fd01:2345:6789::/48", "a ~random~ IPv6 unique-local network"),
            ("::/0", "whole IPv6 address space as network"),
        ):
            with self.subTest(parameters=parameters):
                self.assertIs(
                    self.address_space.describe(description=parameters[1],
                                                ip_parameter=parameters[0]),
                    True,
                )

    def test_describe_ip_parameter_not_valid_typeerror(self):
        """Invalid IP parameter should raise TypeError."""
        for invalid_ in (None, 123, set([3, 2, 1])):
            with self.subTest(invalid_=invalid_):
                invalid_ip_parameter = False
                try:
                    self.address_space.describe(
                        description="invalid ip parameter",
                        ip_parameter=invalid_,
                    )
                except TypeError:
                    invalid_ip_parameter = True
                self.assertTrue(
                    invalid_ip_parameter,
                    "Invalid IP parameter should raise TypeError",
                )

    def test_describe_description_not_str_typeerror(self):
        """Non-str description should raise TypeError."""
        for non_str in (None, 123, set([1, 2, 3])):
            with self.subTest(non_str=non_str):
                non_str_description = False
                try:
                    self.address_space.describe(ip_parameter="123.123.123.123",
                                                description=non_str)
                except TypeError:
                    non_str_description = True
                self.assertTrue(
                    non_str_description,
                    "Non str description should raise TypeError",
                )

    def test_describe_empty_str_valueerror(self):
        """Empty str description should raise ValueError."""
        empty_str_description = False
        try:
            self.address_space.describe(ip_parameter="123.123.123.123",
                                        description="")
        except ValueError:
            empty_str_description = True
        self.assertTrue(
            empty_str_description,
            "Empty str description should raise ValueError",
        )

    def test_description_no_empty_arguments(self):
        """description method with no empty argument list."""
        no_empty_arguments = False
        try:
            self.address_space.description()
        except TypeError:
            no_empty_arguments = True
        self.assertTrue(
            no_empty_arguments,
            "Empty arguments should not be accepted in description",
        )

    def test_description_ip_parameter_not_valid_typeerror(self):
        """Invalid IP parameter should raise TypeError."""
        for invalid_ in (None, 123, set([2, 3, 1])):
            with self.subTest(invalid_=invalid_):
                invalid_ip_parameter = False
                try:
                    self.address_space.description(ip_parameter=invalid_)
                except TypeError:
                    invalid_ip_parameter = True
                self.assertTrue(
                    invalid_ip_parameter,
                    "Invalid IP parameter should raise TypeError",
                )

    def test_describe_then_description(self):
        """describe then description of IP object should return same str."""
        for describe_pair in (
            ("203.0.113.128/25", "should be the same"),
            ("2001:db8::2018:7:12", "hey! an IPv6 Address"),
            ("0.0.0.0", "address 0 for ipv4"),
        ):
            with self.subTest(describe_pair=describe_pair):
                self.address_space.describe(description=describe_pair[1],
                                            ip_parameter=describe_pair[0])
                self.assertEqual(
                    self.address_space.description(describe_pair[0]),
                    describe_pair[1],
                )

    def test_describe_network_then_empty_address_description(self):
        """describe an IP network and retrieve empty str description of
           an address if it is in network range and
           not explicitly described."""
        for data in (
            ("192.0.2.0/24", "a ipv4 test net", "192.0.2.128"),
            ("192.0.2.0/24", "same net, new address", "192.0.2.192"),
            ("10.0.0.0/8", "a large private net", "10.123.45.67"),
            ("fe80::/64", "link-local net", "fe80::ab:cdef"),
            ("2001:db8:abcd::/48", "ipv6 doc net", "2001:db8:abcd::123"),
            ("abcd::/16", "currently outside global ipv6", "abcd:123::abc"),
        ):
            with self.subTest(data=data):
                self.address_space.describe(ip_parameter=data[0],
                                            description=data[1])
                self.assertEqual(self.address_space.description(data[2]),
                                 str(""))

    def test_describe_network_then_empty_subnet_description(self):
        """describe an IP network and retrieve empty str description of
           an subnet if it is in network range and
           not explicitly described."""
        for data in (
            ("192.0.2.0/24", "a ipv4 test net", "192.0.2.0/25"),
            ("192.0.2.0/24", "same net, new subnet", "192.0.2.128/25"),
            ("10.0.0.0/8", "a large private net", "10.123.0.0/16"),
            ("fe80::/64", "link-local net", "fe80::/126"),
            ("2001:db8:abcd::/48", "ipv6 doc net", "2001:db8:abcd:123::/64"),
            ("abcd::/16", "currently outside global ipv6", "abcd:123::/32"),
        ):
            with self.subTest(data=data):
                self.address_space.describe(ip_parameter=data[0],
                                            description=data[1])
                self.assertEqual(self.address_space.description(data[2]),
                                 str(""))

    def test_valid_address_not_in_any_net_should_return_none(self):
        """description should return None if a valid address is
           not described and not in any network."""
        for existing_net in (
                ipaddress.IPv4Network("192.0.2.0/24"),
                ipaddress.ip_network("203.0.113.0/25"),
                "10.0.0.0/16",
                "fe80::/64",
                ipaddress.ip_network("2001:db8::/48"),
                ipaddress.IPv6Network("0:abcd::/32"),
        ):
            self.address_space.describe(description="dull description",
                                        ip_parameter=existing_net)

        for outside_address in (
                "192.0.3.128",
                ipaddress.ip_address("203.0.113.128"),
                ipaddress.IPv4Address("10.128.0.0"),
                "0.0.0.0",
                ipaddress.ip_address("fe80:123::abcd"),
                ipaddress.IPv6Address("2001:db8:abcd::"),
                "::",
        ):
            with self.subTest(outside_address=outside_address):
                self.assertIs(self.address_space.description(outside_address),
                              None)

    def test_valid_networks_not_as_any_subnet_should_return_none(self):
        """description should return None if a valid network is
           not described and not subnet of any network."""
        for existing_net in (
                ipaddress.IPv4Network("192.0.2.0/24"),
                ipaddress.ip_network("203.0.113.0/25"),
                "10.0.0.0/16",
                "fe80::/64",
                ipaddress.ip_network("2001:db8::/48"),
                ipaddress.IPv6Network("0:abcd::/32"),
        ):
            self.address_space.describe(description="dull description",
                                        ip_parameter=existing_net)

        for outside_network in (
                "192.0.3.128/25",
                ipaddress.ip_network("203.0.113.128/26"),
                ipaddress.IPv4Network("10.128.0.0/9"),
                "0.0.0.0/0",
                ipaddress.ip_network("fe80:123::/32"),
                ipaddress.IPv6Network("2001:db8:abcd::/48"),
                "::/0",
        ):
            with self.subTest(outside_network=outside_network):
                self.assertIs(self.address_space.description(outside_network),
                              None)
Example #14
0
 def setUp(self):
     """Set up test fixtures with new AddressSpace."""
     self.address_space = AddressSpace(strict_=False)
Example #15
0
 def setUp(self):
     self.address_space = AddressSpace(strict_=False)
Example #16
0
    def setUp(self):
        """Export AddressSpace's data."""
        self.delegated_tuples = (
            ("2001:db8::/32", "IPv6 documentation network space"),
            ("203.0.113.0/24", "one of IPv4 test net"),
            ("fdab:cdef:1234::/48", "an IPv6 unique-local net"),
            ("192.0.2.0/24", "another IPv4 test net"),
        )
        self.subnet_tuples = (
            ("2001:db8::/48", "zeroed doc subnet"),
            ("2001:db8:1234::/48", "digit doc subnet"),
            ("2001:db8:abcd::/48", "letter doc subnet"),
            ("203.0.113.0/26", "a 1/4 test subnet"),
            ("203.0.113.128/27", "1/8 subnet"),
            ("fdab:cdef:1234:5678::/64", "digit unique local subnet"),
            ("fdab:cdef:1234:abcd::/64", "letter unique local subnet"),
            ("192.0.2.64/26", "another 1/4 test subnet"),
            ("192.0.2.128/25", "1/2 of a test subnet"),
        )
        self.direct_address_tuples = (
            ("2001:db8:9876:5432:10::", "direct IPv6 doc address"),
            ("203.0.113.200", "direct address of a IPv4 test net"),
            ("fdab:cdef:1234:c001::abcd", "direct IPv6 unique-local address"),
            ("192.0.2.12", "direct address of another IPv4 test net"),
        )
        self.subnet_address_tuples = (
            ("2001:db8::123", "digit address of zeroed doc subnet"),
            ("2001:db8::abc", "letter address of zeroed doc subnet"),
            ("2001:db8:1234::abc:123", "mixed address of digit doc subnet"),
            ("2001:db8:1234::f00:ba", "letter address of digit doc subnet"),
            ("2001:db8:abcd:abcd::abcd", "abcd address of letter doc subnet"),
            ("2001:db8:abcd:1234:1234::", "1234 address of letter doc subnet"),
            ("203.0.113.0", "first address of a 1/4 test subnet"),
            ("203.0.113.63", "last address of a 1/4 test subnet"),
            ("203.0.113.130", " almost at begining of 1/8 subnet"),
            ("203.0.113.150", " almost at the end of 1/8 subnet"),
            ("fdab:cdef:1234:5678::1234:5678", "12345678 address"),
            ("fdab:cdef:1234:5678::abcd:abcd", "abcdabcd address"),
            ("fdab:cdef:1234:abcd::7654:321", "reverse number address"),
            ("fdab:cdef:1234:abcd::fe:dcba", "reverse letter address"),
            ("192.0.2.64", "first of another 1/4 test subnet"),
            ("192.0.2.127", "last of another 1/4 test subnet"),
            ("192.0.2.200", "200 of 1/2 of a test subnet"),
            ("192.0.2.234", "234 of 1/2 of a test subnet"),
        )

        self.address_spaces = dict()

        for strict in (False, True):
            self.address_spaces[strict] = AddressSpace(strict_=strict)
            for delegated_data in self.delegated_tuples:
                self.address_spaces[strict].describe_new_delegated_network(
                    network_parameter=delegated_data[0],
                    description=delegated_data[1],
                )
            for subnet_data in self.subnet_tuples:
                self.address_spaces[strict].describe(
                    ip_parameter=subnet_data[0],
                    description=subnet_data[1],
                )
            for address_data in (*self.direct_address_tuples,
                                 *self.subnet_address_tuples):
                self.address_spaces[strict].describe(
                    ip_parameter=address_data[0],
                    description=address_data[1],
                )
Example #17
0
 def setUp(self):
     self.address_space = AddressSpace()
     self.exported_data = self.address_space.export_data()
Example #18
0
class AddressSpace_delete_TestCase(unittest.TestCase):
    """Tests related to delete method in AddressSpace."""
    def setUp(self):
        self.address_space = AddressSpace(strict_=False)

    def test_delete_no_empty_arguments(self):
        """delete method with no empty argument list."""
        no_empty_arguments = False
        try:
            self.address_space.delete()
        except TypeError:
            no_empty_arguments = True
        self.assertTrue(
            no_empty_arguments,
            "Empty arguments should not be accepted in delete",
        )

    def test_delete_keyword_only_no_positional_arguments(self):
        """delete method as keyword only, without positional parameters."""
        no_positional_arguments = False
        try:
            self.address_space.delete("203.0.113.128", True)
        except TypeError:
            no_positional_arguments = True
        self.assertTrue(
            no_positional_arguments,
            "No positional argument should be accepted in delete",
        )

    def test_delete_trying_to_delete_object_not_in_space_error_raise(self):
        """Trying to delete an IP object not in space should raise Error."""
        no_ip_object = False
        try:
            self.address_space.delete(
                ip_parameter="203.0.113.128",
                cascade=True,
            )
        except IPObjectNotInSpaceError:
            no_ip_object = True
        self.assertTrue(
            no_ip_object,
            "Cannot delete IP object without explicit description",
        )

    def test_delete_deleting_object_in_space_returns_true(self):
        """Deleting a described IP object should return True."""
        for parameter_description in (
            ("203.0.113.128", "an IPv4 test net address"),
            ("2001:db8:abcd::/48", "an IPv6 doc subnet"),
            ("123.123.123.123", "123 is nice"),
            ("203.0.113.129", "Second subnet gateway"),
            ("192.0.2.123", "123 is nice, test net"),
            ("2001:db8::abcd:ef12", "ipv6 doc address"),
            ("2000::", "first global address for now"),
            ("fe80::", "even link-local?"),
            ("10.0.0.0/16", "a private IPv4 network"),
            ("203.0.113.128/25", "part of a test net"),
            ("0.0.0.0/0", "whole IPv4 address space as network"),
            ("2001:db8:1234:5678::/64", "a documentation IPv6 network"),
            ("fe80::/64", "IPv6 link-local network"),
            ("fd01:2345:6789::/48", "a ~random~ IPv6 unique-local network"),
            ("::/0", "whole IPv6 address space as network"),
        ):
            with self.subTest(parameter_description=parameter_description):
                self.assertTrue(
                    self.address_space.describe(
                        ip_parameter=parameter_description[0],
                        description=parameter_description[1],
                    ))
                self.assertTrue(
                    self.address_space.delete(
                        ip_parameter=parameter_description[0],
                        cascade=True,
                    ),
                    "Deleting a described IP object should return True.",
                )

    def test_delete_after_deleting_object_description_should_be_none(self):
        """Description of a deleted IP object should return None
           if no other IP object."""
        for parameter_description in (
            ("203.0.113.128", "an IPv4 test net address"),
            ("2001:db8:abcd::/48", "an IPv6 doc subnet"),
            ("123.123.123.123", "123 is nice"),
            ("203.0.113.129", "Second subnet gateway"),
            ("192.0.2.123", "123 is nice, test net"),
            ("2001:db8::abcd:ef12", "ipv6 doc address"),
            ("2000::", "first global address for now"),
            ("fe80::", "even link-local?"),
            ("10.0.0.0/16", "a private IPv4 network"),
            ("203.0.113.128/25", "part of a test net"),
            ("0.0.0.0/0", "whole IPv4 address space as network"),
            ("2001:db8:1234:5678::/64", "a documentation IPv6 network"),
            ("fe80::/64", "IPv6 link-local network"),
            ("fd01:2345:6789::/48", "a ~random~ IPv6 unique-local network"),
            ("::/0", "whole IPv6 address space as network"),
        ):
            with self.subTest(parameter_description=parameter_description):
                self.assertTrue(
                    self.address_space.describe(
                        ip_parameter=parameter_description[0],
                        description=parameter_description[1],
                    ))
                self.assertTrue(
                    self.address_space.delete(
                        ip_parameter=parameter_description[0],
                        cascade=True,
                    ),
                    "Deleting a described IP object should return True.",
                )
                self.assertIs(
                    self.address_space.description(parameter_description[0]),
                    None,
                    "No IP object, so description should be None",
                )