summaryrefslogtreecommitdiffstats
path: root/netaddr/tests/strategy/test_ipv6_strategy.py
blob: 34c278e6a0d7f975d2a02f142bc0e91292069b20 (plain)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import platform
import sys

import pytest

from netaddr import AddrFormatError
from netaddr.strategy import ipv6


def test_strategy_ipv6():
    b = '0000000000000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:0000000000000000:1111111111111111:1111111111111110'
    i = 4294967294
    t = (0, 0, 0, 0, 0, 0, 0xffff, 0xfffe)
    s = '::255.255.255.254'

    assert ipv6.bits_to_int(b) == i
    assert ipv6.int_to_bits(i) == b

    assert ipv6.int_to_str(i) == s
    assert ipv6.str_to_int(s) == i

    assert ipv6.int_to_words(i) == t
    assert ipv6.words_to_int(t) == i
    assert ipv6.words_to_int(list(t)) == i


@pytest.mark.skipif(sys.version_info > (3,), reason="requires python 2.x")
def test_strategy_ipv6_py2():
    i = 4294967294
    p = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe'
    assert ipv6.int_to_packed(i) == p
    assert ipv6.packed_to_int(p) == 4294967294


@pytest.mark.skipif(sys.version_info < (3,), reason="requires python 3.x")
def test_strategy_ipv6_py3():
    i = 4294967294
    p = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe'
    assert ipv6.int_to_packed(i) == p
    assert ipv6.packed_to_int(p) == 4294967294


@pytest.mark.parametrize('str_value', (
    '2001:0db8:0000:0000:0000:0000:1428:57ab',
    '2001:0db8:0000:0000:0000::1428:57ab',
    '2001:0db8:0:0:0:0:1428:57ab',
    '2001:0db8:0:0::1428:57ab',
    '2001:0db8::1428:57ab',
    '2001:0DB8:0000:0000:0000:0000:1428:57AB',
    '2001:DB8::1428:57AB',
))
def test_strategy_ipv6_equivalent_variants(str_value):
    assert ipv6.str_to_int(str_value) == 42540766411282592856903984951992014763


@pytest.mark.parametrize('str_value', (
    #   Long forms.
    'FEDC:BA98:7654:3210:FEDC:BA98:7654:3210',
    '1080:0:0:0:8:800:200C:417A',   #   a unicast address
    'FF01:0:0:0:0:0:0:43',      	#   a multicast address
    '0:0:0:0:0:0:0:1',          	#   the loopback address
    '0:0:0:0:0:0:0:0',          	#   the unspecified addresses

    #   Short forms.
    '1080::8:800:200C:417A',    	#   a unicast address
    'FF01::43',                 	#   a multicast address
    '::1',                      	#   the loopback address
    '::',                       	#   the unspecified addresses

    #   IPv4 compatible forms.
    '::192.0.2.1',
    '::ffff:192.0.2.1',
    '0:0:0:0:0:0:192.0.2.1',
    '0:0:0:0:0:FFFF:192.0.2.1',
    '0:0:0:0:0:0:13.1.68.3',
    '0:0:0:0:0:FFFF:129.144.52.38',
    '::13.1.68.3',
    '::FFFF:129.144.52.38',

    #   Other tests.
    '1::',
    '::ffff',
    'ffff::',
    'ffff::ffff',
    '0:1:2:3:4:5:6:7',
    '8:9:a:b:c:d:e:f',
    '0:0:0:0:0:0:0:0',
    'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
))
def test_strategy_ipv6_valid_str(str_value):
    assert ipv6.valid_str(str_value)


@pytest.mark.parametrize('str_value', (
    'g:h:i:j:k:l:m:n',      # bad chars.
    '0:0:0:0:0:0:0:0:0',    # too long,
    #   Unexpected types.
    [],
    (),
    {},
    True,
    False,
))
def test_strategy_ipv6_is_not_valid_str(str_value):
    assert not ipv6.valid_str(str_value)


def test_strategy_ipv6_valid_str_exception_on_empty_string():
    with pytest.raises(AddrFormatError):
        ipv6.valid_str('')


@pytest.mark.parametrize(('long_form', 'short_form'), (
    ('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', 'fedc:ba98:7654:3210:fedc:ba98:7654:3210'),
    ('1080:0:0:0:8:800:200C:417A', '1080::8:800:200c:417a'), # unicast address
    ('FF01:0:0:0:0:0:0:43', 'ff01::43'), # multicast address
    ('0:0:0:0:0:0:0:1', '::1'),          # loopback address
    ('0:0:0:0:0:0:0:0', '::'),           # unspecified addresses
))
def test_strategy_ipv6_string_compaction(long_form, short_form):
    int_val = ipv6.str_to_int(long_form)
    calc_short_form = ipv6.int_to_str(int_val)
    assert calc_short_form == short_form


def test_strategy_ipv6_mapped_and_compatible_ipv4_string_formatting():
    assert ipv6.int_to_str(0xffffff) == '::0.255.255.255'
    assert ipv6.int_to_str(0xffffffff) == '::255.255.255.255'
    assert ipv6.int_to_str(0x1ffffffff) == '::1:ffff:ffff'
    assert ipv6.int_to_str(0xffffffffffff) == '::ffff:255.255.255.255'
    assert ipv6.int_to_str(0xfffeffffffff) == '::fffe:ffff:ffff'
    assert ipv6.int_to_str(0xffffffffffff) == '::ffff:255.255.255.255'
    assert ipv6.int_to_str(0xfffffffffff1) == '::ffff:255.255.255.241'
    assert ipv6.int_to_str(0xfffffffffffe) == '::ffff:255.255.255.254'
    assert ipv6.int_to_str(0xffffffffff00) == '::ffff:255.255.255.0'
    assert ipv6.int_to_str(0xffffffff0000) == '::ffff:255.255.0.0'
    assert ipv6.int_to_str(0xffffff000000) == '::ffff:255.0.0.0'
    assert ipv6.int_to_str(0xffff000000) == '::ff:ff00:0'
    assert ipv6.int_to_str(0x1ffff00000000) == '::1:ffff:0:0'
    # So this is strange. Even though on Windows we get decimal notation in a lot of the addresses above,
    # in case of 0.0.0.0 we get hex instead, unless it's Python 2, then we get decimal... unless it's
    # actually PyPy Python 2, then we always get hex (again, only on Windows). Worth investigating, putting
    # the conditional assert here for now to make this visible.
    if platform.system() == 'Windows' and (
            platform.python_version() >= '3.0' or platform.python_implementation() == 'PyPy'
    ):
        assert ipv6.int_to_str(0xffff00000000) == '::ffff:0:0'
    else:
        assert ipv6.int_to_str(0xffff00000000) == '::ffff:0.0.0.0'


def test_strategy_ipv6_str_to_int_behaviour_legacy_mode():
    assert ipv6.str_to_int('::127') == 295

    with pytest.raises(AddrFormatError):
        ipv6.str_to_int('::0x7f')

    assert ipv6.str_to_int('::0177') == 375

    with pytest.raises(AddrFormatError):
        ipv6.str_to_int('::127.1')

    with pytest.raises(AddrFormatError):
        ipv6.str_to_int('::0x7f.1')

    with pytest.raises(AddrFormatError):
        ipv6.str_to_int('::0177.1')

    assert ipv6.str_to_int('::127.0.0.1') == 2130706433