Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 297b143

Browse files
committed
Issue 14814: Further error case testing coverage and cleanups
1 parent 540715a commit 297b143

2 files changed

Lines changed: 93 additions & 98 deletions

File tree

Lib/ipaddress.py

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ def _split_optional_netmask(address):
163163
raise AddressValueError("Only one '/' permitted in %r" % address)
164164
return addr
165165

166+
166167
def _find_address_range(addresses):
167168
"""Find a sequence of IPv#Address.
168169
@@ -408,6 +409,8 @@ def get_mixed_type_key(obj):
408409
class _TotalOrderingMixin:
409410
# Helper that derives the other comparison operations from
410411
# __lt__ and __eq__
412+
# We avoid functools.total_ordering because it doesn't handle
413+
# NotImplemented correctly yet (http://bugs.python.org/issue10042)
411414
def __eq__(self, other):
412415
raise NotImplementedError
413416
def __ne__(self, other):
@@ -455,6 +458,22 @@ def version(self):
455458
msg = '%200s has no version specified' % (type(self),)
456459
raise NotImplementedError(msg)
457460

461+
def _check_int_address(self, address):
462+
if address < 0:
463+
msg = "%d (< 0) is not permitted as an IPv%d address"
464+
raise AddressValueError(msg % (address, self._version))
465+
if address > self._ALL_ONES:
466+
msg = "%d (>= 2**%d) is not permitted as an IPv%d address"
467+
raise AddressValueError(msg % (address, self._max_prefixlen,
468+
self._version))
469+
470+
def _check_packed_address(self, address, expected_len):
471+
address_len = len(address)
472+
if address_len != expected_len:
473+
msg = "%r (len %d != %d) is not permitted as an IPv%d address"
474+
raise AddressValueError(msg % (address, address_len,
475+
expected_len, self._version))
476+
458477
def _ip_int_from_prefix(self, prefixlen=None):
459478
"""Turn the prefix length netmask into a int for comparison.
460479
@@ -1215,16 +1234,13 @@ def __init__(self, address):
12151234

12161235
# Efficient constructor from integer.
12171236
if isinstance(address, int):
1237+
self._check_int_address(address)
12181238
self._ip = address
1219-
if address < 0 or address > self._ALL_ONES:
1220-
raise AddressValueError(address)
12211239
return
12221240

12231241
# Constructing from a packed address
12241242
if isinstance(address, bytes):
1225-
if len(address) != 4:
1226-
msg = "Packed address %r must be exactly 4 bytes"
1227-
raise AddressValueError(msg % address)
1243+
self._check_packed_address(address, 4)
12281244
self._ip = struct.unpack('!I', address)[0]
12291245
return
12301246

@@ -1368,23 +1384,17 @@ def __init__(self, address, strict=True):
13681384

13691385
# Constructing from a packed address
13701386
if isinstance(address, bytes):
1371-
if len(address) != 4:
1372-
msg = "Packed address %r must be exactly 4 bytes"
1373-
raise AddressValueError(msg % address)
1374-
self.network_address = IPv4Address(
1375-
struct.unpack('!I', address)[0])
1387+
self.network_address = IPv4Address(address)
13761388
self._prefixlen = self._max_prefixlen
13771389
self.netmask = IPv4Address(self._ALL_ONES)
13781390
#fixme: address/network test here
13791391
return
13801392

13811393
# Efficient constructor from integer.
13821394
if isinstance(address, int):
1395+
self.network_address = IPv4Address(address)
13831396
self._prefixlen = self._max_prefixlen
13841397
self.netmask = IPv4Address(self._ALL_ONES)
1385-
if address < 0 or address > self._ALL_ONES:
1386-
raise AddressValueError(address)
1387-
self.network_address = IPv4Address(address)
13881398
#fixme: address/network test here.
13891399
return
13901400

@@ -1868,16 +1878,13 @@ def __init__(self, address):
18681878

18691879
# Efficient constructor from integer.
18701880
if isinstance(address, int):
1881+
self._check_int_address(address)
18711882
self._ip = address
1872-
if address < 0 or address > self._ALL_ONES:
1873-
raise AddressValueError(address)
18741883
return
18751884

18761885
# Constructing from a packed address
18771886
if isinstance(address, bytes):
1878-
if len(address) != 16:
1879-
msg = "Packed address %r must be exactly 16 bytes"
1880-
raise AddressValueError(msg % address)
1887+
self._check_packed_address(address, 16)
18811888
tmp = struct.unpack('!QQ', address)
18821889
self._ip = (tmp[0] << 64) | tmp[1]
18831890
return
@@ -2014,20 +2021,14 @@ def __init__(self, address, strict=True):
20142021

20152022
# Efficient constructor from integer.
20162023
if isinstance(address, int):
2017-
if address < 0 or address > self._ALL_ONES:
2018-
raise AddressValueError(address)
20192024
self.network_address = IPv6Address(address)
20202025
self._prefixlen = self._max_prefixlen
20212026
self.netmask = IPv6Address(self._ALL_ONES)
20222027
return
20232028

20242029
# Constructing from a packed address
20252030
if isinstance(address, bytes):
2026-
if len(address) != 16:
2027-
msg = "Packed address %r must be exactly 16 bytes"
2028-
raise AddressValueError(msg % address)
2029-
tmp = struct.unpack('!QQ', address)
2030-
self.network_address = IPv6Address((tmp[0] << 64) | tmp[1])
2031+
self.network_address = IPv6Address(address)
20312032
self._prefixlen = self._max_prefixlen
20322033
self.netmask = IPv6Address(self._ALL_ONES)
20332034
return

Lib/test/test_ipaddress.py

Lines changed: 67 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ class ErrorReporting(unittest.TestCase):
2323
# address parts) that don't have an obvious home in the main test
2424
# suite
2525

26+
@property
27+
def factory(self):
28+
raise NotImplementedError
29+
2630
@contextlib.contextmanager
2731
def assertCleanError(self, exc_type, details, *args):
2832
"""
@@ -49,11 +53,64 @@ def assertNetmaskError(self, details, *args):
4953
return self.assertCleanError(ipaddress.NetmaskValueError,
5054
details, *args)
5155

52-
class AddressErrors_v4(ErrorReporting):
56+
class CommonErrorsMixin:
5357

5458
def test_empty_address(self):
5559
with self.assertAddressError("Address cannot be empty"):
56-
ipaddress.IPv4Address("")
60+
self.factory("")
61+
62+
def test_floats_rejected(self):
63+
with self.assertAddressError(re.escape(repr("1.0"))):
64+
self.factory(1.0)
65+
66+
class CommonErrorsMixin_v4(CommonErrorsMixin):
67+
68+
def test_negative_ints_rejected(self):
69+
msg = "-1 (< 0) is not permitted as an IPv4 address"
70+
with self.assertAddressError(re.escape(msg)):
71+
self.factory(-1)
72+
73+
def test_large_ints_rejected(self):
74+
msg = "%d (>= 2**32) is not permitted as an IPv4 address"
75+
with self.assertAddressError(re.escape(msg % 2**32)):
76+
self.factory(2**32)
77+
78+
def test_bad_packed_length(self):
79+
def assertBadLength(length):
80+
addr = b'\x00' * length
81+
msg = "%r (len %d != 4) is not permitted as an IPv4 address"
82+
with self.assertAddressError(re.escape(msg % (addr, length))):
83+
self.factory(addr)
84+
85+
assertBadLength(3)
86+
assertBadLength(5)
87+
88+
class CommonErrorsMixin_v6(CommonErrorsMixin):
89+
90+
def test_negative_ints_rejected(self):
91+
msg = "-1 (< 0) is not permitted as an IPv6 address"
92+
with self.assertAddressError(re.escape(msg)):
93+
self.factory(-1)
94+
95+
def test_large_ints_rejected(self):
96+
msg = "%d (>= 2**128) is not permitted as an IPv6 address"
97+
with self.assertAddressError(re.escape(msg % 2**128)):
98+
self.factory(2**128)
99+
100+
def test_bad_packed_length(self):
101+
def assertBadLength(length):
102+
addr = b'\x00' * length
103+
msg = "%r (len %d != 16) is not permitted as an IPv6 address"
104+
with self.assertAddressError(re.escape(msg % (addr, length))):
105+
self.factory(addr)
106+
self.factory(addr)
107+
108+
assertBadLength(15)
109+
assertBadLength(17)
110+
111+
112+
class AddressErrors_v4(ErrorReporting, CommonErrorsMixin_v4):
113+
factory = ipaddress.IPv4Address
57114

58115
def test_network_passed_as_address(self):
59116
addr = "127.0.0.1/24"
@@ -133,22 +190,9 @@ def assertBadOctet(addr, octet):
133190
assertBadOctet("12345.67899.-54321.-98765", 12345)
134191
assertBadOctet("257.0.0.0", 257)
135192

136-
def test_bad_packed_length(self):
137-
def assertBadLength(length):
138-
addr = b'\x00' * length
139-
msg = "Packed address %r must be exactly 4 bytes" % addr
140-
with self.assertAddressError(re.escape(msg)):
141-
ipaddress.IPv4Address(addr)
142-
143-
assertBadLength(3)
144-
assertBadLength(5)
145193

146-
147-
class AddressErrors_v6(ErrorReporting):
148-
149-
def test_empty_address(self):
150-
with self.assertAddressError("Address cannot be empty"):
151-
ipaddress.IPv6Address("")
194+
class AddressErrors_v6(ErrorReporting, CommonErrorsMixin_v6):
195+
factory = ipaddress.IPv6Address
152196

153197
def test_network_passed_as_address(self):
154198
addr = "::1/24"
@@ -277,24 +321,10 @@ def assertBadPart(addr, part):
277321
assertBadPart("02001:db8::", "02001")
278322
assertBadPart('2001:888888::1', "888888")
279323

280-
def test_bad_packed_length(self):
281-
def assertBadLength(length):
282-
addr = b'\x00' * length
283-
msg = "Packed address %r must be exactly 16 bytes" % addr
284-
with self.assertAddressError(re.escape(msg)):
285-
ipaddress.IPv6Address(addr)
286-
287-
assertBadLength(15)
288-
assertBadLength(17)
289-
290324

291-
class NetmaskErrorsMixin_v4:
325+
class NetmaskErrorsMixin_v4(CommonErrorsMixin_v4):
292326
"""Input validation on interfaces and networks is very similar"""
293327

294-
@property
295-
def factory(self):
296-
raise NotImplementedError
297-
298328
def test_split_netmask(self):
299329
addr = "1.2.3.4/32/24"
300330
with self.assertAddressError("Only one '/' permitted in %r" % addr):
@@ -305,7 +335,8 @@ def assertBadAddress(addr, details):
305335
with self.assertAddressError(details):
306336
self.factory(addr)
307337

308-
assertBadAddress("", "Address cannot be empty")
338+
assertBadAddress("/", "Address cannot be empty")
339+
assertBadAddress("/8", "Address cannot be empty")
309340
assertBadAddress("bogus", "Expected 4 octets")
310341
assertBadAddress("google.com", "Expected 4 octets")
311342
assertBadAddress("10/8", "Expected 4 octets")
@@ -325,31 +356,16 @@ def assertBadNetmask(addr, netmask):
325356
assertBadNetmask("1.1.1.1", "1.a.2.3")
326357
assertBadNetmask("1.1.1.1", "pudding")
327358

328-
def test_bad_packed_length(self):
329-
def assertBadLength(length):
330-
addr = b'\x00' * length
331-
msg = "Packed address %r must be exactly 4 bytes" % addr
332-
with self.assertAddressError(re.escape(msg)):
333-
self.factory(addr)
334-
335-
assertBadLength(3)
336-
assertBadLength(5)
337-
338-
339359
class InterfaceErrors_v4(ErrorReporting, NetmaskErrorsMixin_v4):
340360
factory = ipaddress.IPv4Interface
341361

342362
class NetworkErrors_v4(ErrorReporting, NetmaskErrorsMixin_v4):
343363
factory = ipaddress.IPv4Network
344364

345365

346-
class NetmaskErrorsMixin_v6:
366+
class NetmaskErrorsMixin_v6(CommonErrorsMixin_v6):
347367
"""Input validation on interfaces and networks is very similar"""
348368

349-
@property
350-
def factory(self):
351-
raise NotImplementedError
352-
353369
def test_split_netmask(self):
354370
addr = "cafe:cafe::/128/190"
355371
with self.assertAddressError("Only one '/' permitted in %r" % addr):
@@ -360,7 +376,8 @@ def assertBadAddress(addr, details):
360376
with self.assertAddressError(details):
361377
self.factory(addr)
362378

363-
assertBadAddress("", "Address cannot be empty")
379+
assertBadAddress("/", "Address cannot be empty")
380+
assertBadAddress("/8", "Address cannot be empty")
364381
assertBadAddress("google.com", "At least 3 parts")
365382
assertBadAddress("1.2.3.4", "At least 3 parts")
366383
assertBadAddress("10/8", "At least 3 parts")
@@ -378,17 +395,6 @@ def assertBadNetmask(addr, netmask):
378395
assertBadNetmask("::1", "129")
379396
assertBadNetmask("::1", "pudding")
380397

381-
def test_bad_packed_length(self):
382-
def assertBadLength(length):
383-
addr = b'\x00' * length
384-
msg = "Packed address %r must be exactly 16 bytes" % addr
385-
with self.assertAddressError(re.escape(msg)):
386-
self.factory(addr)
387-
388-
assertBadLength(15)
389-
assertBadLength(17)
390-
391-
392398
class InterfaceErrors_v6(ErrorReporting, NetmaskErrorsMixin_v6):
393399
factory = ipaddress.IPv6Interface
394400

@@ -585,10 +591,6 @@ def testGetNetwork(self):
585591
def testIpFromInt(self):
586592
self.assertEqual(self.ipv4_interface._ip,
587593
ipaddress.IPv4Interface(16909060)._ip)
588-
self.assertRaises(ipaddress.AddressValueError,
589-
ipaddress.IPv4Interface, 2**32)
590-
self.assertRaises(ipaddress.AddressValueError,
591-
ipaddress.IPv4Interface, -1)
592594

593595
ipv4 = ipaddress.ip_network('1.2.3.4')
594596
ipv6 = ipaddress.ip_network('2001:658:22a:cafe:200:0:0:1')
@@ -598,14 +600,6 @@ def testIpFromInt(self):
598600
v6_int = 42540616829182469433547762482097946625
599601
self.assertEqual(self.ipv6_interface._ip,
600602
ipaddress.IPv6Interface(v6_int)._ip)
601-
self.assertRaises(ipaddress.AddressValueError,
602-
ipaddress.IPv6Interface, 2**128)
603-
self.assertRaises(ipaddress.AddressValueError,
604-
ipaddress.IPv6Interface, -1)
605-
self.assertRaises(ipaddress.AddressValueError,
606-
ipaddress.IPv6Network, 2**128)
607-
self.assertRaises(ipaddress.AddressValueError,
608-
ipaddress.IPv6Network, -1)
609603

610604
self.assertEqual(ipaddress.ip_network(self.ipv4_address._ip).version,
611605
4)

0 commit comments

Comments
 (0)