1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
import pytest
from netaddr import IPAddress
# Excluding is_ipv4_compat as we'll likely be dropping it
unicast = 1 << 0
multicast = 1 << 1
loopback = 1 << 2
private = 1 << 3
link_local = 1 << 4
reserved = 1 << 5
ipv4_mapped = 1 << 6
hostmask = 1 << 7
netmask = 1 << 8
ipv4_private_use = 1 << 9
global_ = 1 << 10
ipv6_unique_local = 1 << 11
flags = {
'unicast': unicast,
'multicast': multicast,
'loopback': loopback,
'private': private,
'link_local': link_local,
'reserved': reserved,
'ipv4_mapped': ipv4_mapped,
'hostmask': hostmask,
'netmask': netmask,
'ipv4_private_use': ipv4_private_use,
'global': global_,
'ipv6_unique_local': ipv6_unique_local,
}
@pytest.mark.parametrize('text_address,categories', [
# IPv4
['0.0.0.0', reserved | hostmask | netmask | unicast],
['0.0.1.255', hostmask | reserved | unicast | hostmask],
['0.255.255.255', reserved | hostmask | unicast],
['10.0.0.1', ipv4_private_use | private | unicast],
['62.125.24.5', global_ | unicast],
['100.64.0.0', private | unicast],
['127.0.0.0', reserved | loopback | unicast | reserved],
['127.0.0.1', loopback | reserved | unicast],
['172.24.0.1', ipv4_private_use | private | unicast],
['127.255.255.255', reserved | hostmask | loopback | unicast],
['169.254.0.0', link_local | private | unicast],
['192.0.0.0', netmask | private | unicast],
['192.0.0.8', private | unicast],
['192.0.0.9', global_ | private | unicast],
['192.0.0.10', global_ | private | unicast],
['192.0.0.11', private | unicast],
['192.0.0.170', private | unicast],
['192.0.0.171', private | unicast],
['192.0.2.0', reserved | unicast],
['192.0.2.1', reserved | unicast],
['192.0.2.255', reserved | unicast],
['192.31.196.0', global_ | unicast],
['192.52.193.0', global_ | unicast],
['192.88.99.0', global_ | reserved | unicast],
['192.88.99.255', global_ | reserved | unicast],
['192.168.0.1', ipv4_private_use | private | unicast],
['192.175.48.0', global_ | unicast],
['198.18.0.0', private | unicast],
['198.19.255.255', private | unicast],
['198.51.100.0', reserved | unicast],
['203.0.113.0', reserved | unicast],
['233.252.0.0', global_ | reserved | multicast],
['233.252.0.255', global_ | reserved | multicast],
['239.192.0.1', global_ | private | multicast],
['253.0.0.1', reserved | unicast],
['255.255.254.0', netmask | reserved | unicast],
# IPv6
['::', hostmask | netmask | reserved | unicast],
['::1', loopback | hostmask | reserved | unicast],
['::ffff:0.0.0.0', ipv4_mapped | reserved | unicast],
['::ffff:1.1.1.1', ipv4_mapped | reserved | unicast],
['64:ff9b::', global_ | reserved | unicast],
['64:ff9b:1::', reserved | unicast],
['100::', reserved | unicast],
['2001::', unicast],
['2001:1::1', global_ | unicast],
['2001:1::2', global_ | unicast],
['2001:2::', unicast],
['2001:3::', global_ | unicast],
['2001:4:112::', global_ | unicast],
['2001:10::', unicast],
['2001:20::', global_ | unicast],
['2001:30::', global_ | unicast],
['2001:db8::', unicast],
['2002::', unicast],
['2620:4f:8000::', global_ | unicast],
['fc00::1', ipv6_unique_local | private | unicast],
['fe80::1', private | unicast | link_local],
['ff00::1', global_ | reserved | multicast],
])
def test_ip_categories(text_address, categories):
address = IPAddress(text_address)
methods = [
getattr(address, name)
for name in dir(address) if name.startswith('is_') and name != 'is_ipv4_compat'
]
for method in methods:
name = method.__name__.replace('is_', '')
flag = flags[name]
got_value = method()
expected_value = bool(categories & flag)
assert got_value == expected_value, 'Expected is_%s() value to be %s' % (name, expected_value)
categories &= ~flag
# Just one final check to make sure we haven't missed any flags
assert categories == 0
|