# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license

import socket
import sys
import unittest

import dns.exception
import dns.ipv4
import dns.ipv6


class IPv4Tests(unittest.TestCase):
    def test_valid(self):
        valid = (
            "1.2.3.4",
            "11.22.33.44",
            "254.7.237.98",
            "192.168.1.26",
            "192.168.1.1",
            "13.1.68.3",
            "129.144.52.38",
            "254.157.241.86",
            "12.34.56.78",
            "192.0.2.128",
        )
        for s in valid:
            self.assertEqual(dns.ipv4.inet_aton(s), socket.inet_pton(socket.AF_INET, s))

    def test_invalid(self):
        invalid = (
            "",
            ".",
            "..",
            "400.2.3.4",
            "260.2.3.4",
            "256.2.3.4",
            "1.256.3.4",
            "1.2.256.4",
            "1.2.3.256",
            "300.2.3.4",
            "1.300.3.4",
            "1.2.300.4",
            "1.2.3.300",
            "900.2.3.4",
            "1.900.3.4",
            "1.2.900.4",
            "1.2.3.900",
            "300.300.300.300",
            "3000.30.30.30",
            "255Z255X255Y255",
            "192x168.1.26",
            "2.3.4",
            "257.1.2.3",
            "00.00.00.00",
            "000.000.000.000",
            "256.256.256.256",
            "255255.255.255",
            "255.255255.255",
            "255.255.255255",
            "1...",
            "1.2..",
            "1.2.3.",
            ".2..",
            ".2.3.",
            ".2.3.4",
            "..3.",
            "..3.4",
            "...4",
            ".1.2.3.4",
            "1.2.3.4.",
            " 1.2.3.4",
            "1.2.3.4 ",
            " 1.2.3.4 ",
            "::",
        )
        for s in invalid:
            with self.assertRaises(
                dns.exception.SyntaxError, msg=f'invalid IPv4 address: "{s}"'
            ):
                dns.ipv4.inet_aton(s)


class IPv6Tests(unittest.TestCase):
    def test_valid(self):
        valid = (
            "::1",
            "::",
            "0:0:0:0:0:0:0:1",
            "0:0:0:0:0:0:0:0",
            "2001:DB8:0:0:8:800:200C:417A",
            "FF01:0:0:0:0:0:0:101",
            "2001:DB8::8:800:200C:417A",
            "FF01::101",
            "fe80::217:f2ff:fe07:ed62",
            "2001:0000:1234:0000:0000:C1C0:ABCD:0876",
            "3ffe:0b00:0000:0000:0001:0000:0000:000a",
            "FF02:0000:0000:0000:0000:0000:0000:0001",
            "0000:0000:0000:0000:0000:0000:0000:0001",
            "0000:0000:0000:0000:0000:0000:0000:0000",
            "2::10",
            "ff02::1",
            "fe80::",
            "2002::",
            "2001:db8::",
            "2001:0db8:1234::",
            "::ffff:0:0",
            "1:2:3:4:5:6:7:8",
            "1:2:3:4:5:6::8",
            "1:2:3:4:5::8",
            "1:2:3:4::8",
            "1:2:3::8",
            "1:2::8",
            "1::8",
            "1::2:3:4:5:6:7",
            "1::2:3:4:5:6",
            "1::2:3:4:5",
            "1::2:3:4",
            "1::2:3",
            "::2:3:4:5:6:7:8",
            "::2:3:4:5:6:7",
            "::2:3:4:5:6",
            "::2:3:4:5",
            "::2:3:4",
            "::2:3",
            "::8",
            "1:2:3:4:5:6::",
            "1:2:3:4:5::",
            "1:2:3:4::",
            "1:2:3::",
            "1:2::",
            "1::",
            "1:2:3:4:5::7:8",
            "1:2:3:4::7:8",
            "1:2:3::7:8",
            "1:2::7:8",
            "1::7:8",
            "1:2:3:4:5:6:1.2.3.4",
            "1:2:3:4:5::1.2.3.4",
            "1:2:3:4::1.2.3.4",
            "1:2:3::1.2.3.4",
            "1:2::1.2.3.4",
            "1::1.2.3.4",
            "1:2:3:4::5:1.2.3.4",
            "1:2:3::5:1.2.3.4",
            "1:2:3::5:1.2.3.4",
            "1:2::5:1.2.3.4",
            "1::5:1.2.3.4",
            "1::5:11.22.33.44",
            "fe80::217:f2ff:254.7.237.98",
            "::ffff:192.168.1.26",
            "::ffff:192.168.1.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",
            "fe80:0:0:0:204:61ff:254.157.241.86",
            "fe80::204:61ff:254.157.241.86",
            "::ffff:12.34.56.78",
            "::ffff:192.0.2.128",
            "fe80:0000:0000:0000:0204:61ff:fe9d:f156",
            "fe80:0:0:0:204:61ff:fe9d:f156",
            "fe80::204:61ff:fe9d:f156",
            "fe80::1",
            "::ffff:c000:280",
            "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
            "2001:db8:85a3:0:0:8a2e:370:7334",
            "2001:db8:85a3::8a2e:370:7334",
            "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:db8::1428:57ab",
            "::ffff:0c22:384e",
            "2001:0db8:1234:0000:0000:0000:0000:0000",
            "2001:0db8:1234:ffff:ffff:ffff:ffff:ffff",
            "2001:db8:a::123",
            "1111:2222:3333:4444:5555:6666:7777:8888",
            "1111:2222:3333:4444:5555:6666:7777::",
            "1111:2222:3333:4444:5555:6666::",
            "1111:2222:3333:4444:5555::",
            "1111:2222:3333:4444::",
            "1111:2222:3333::",
            "1111:2222::",
            "1111::",
            "1111:2222:3333:4444:5555:6666::8888",
            "1111:2222:3333:4444:5555::8888",
            "1111:2222:3333:4444::8888",
            "1111:2222:3333::8888",
            "1111:2222::8888",
            "1111::8888",
            "::8888",
            "1111:2222:3333:4444:5555::7777:8888",
            "1111:2222:3333:4444::7777:8888",
            "1111:2222:3333::7777:8888",
            "1111:2222::7777:8888",
            "1111::7777:8888",
            "::7777:8888",
            "1111:2222:3333:4444::6666:7777:8888",
            "1111:2222:3333::6666:7777:8888",
            "1111:2222::6666:7777:8888",
            "1111::6666:7777:8888",
            "::6666:7777:8888",
            "1111:2222:3333::5555:6666:7777:8888",
            "1111:2222::5555:6666:7777:8888",
            "1111::5555:6666:7777:8888",
            "::5555:6666:7777:8888",
            "1111:2222::4444:5555:6666:7777:8888",
            "1111::4444:5555:6666:7777:8888",
            "::4444:5555:6666:7777:8888",
            "1111::3333:4444:5555:6666:7777:8888",
            "::3333:4444:5555:6666:7777:8888",
            "::2222:3333:4444:5555:6666:7777:8888",
            "1111:2222:3333:4444:5555:6666:123.123.123.123",
            "1111:2222:3333:4444:5555::123.123.123.123",
            "1111:2222:3333:4444::123.123.123.123",
            "1111:2222:3333::123.123.123.123",
            "1111:2222::123.123.123.123",
            "1111::123.123.123.123",
            "::123.123.123.123",
            "1111:2222:3333:4444::6666:123.123.123.123",
            "1111:2222:3333::6666:123.123.123.123",
            "1111:2222::6666:123.123.123.123",
            "1111::6666:123.123.123.123",
            "::6666:123.123.123.123",
            "1111:2222:3333::5555:6666:123.123.123.123",
            "1111:2222::5555:6666:123.123.123.123",
            "1111::5555:6666:123.123.123.123",
            "::5555:6666:123.123.123.123",
            "1111:2222::4444:5555:6666:123.123.123.123",
            "1111::4444:5555:6666:123.123.123.123",
            "::4444:5555:6666:123.123.123.123",
            "1111::3333:4444:5555:6666:123.123.123.123",
            "::2222:3333:4444:5555:6666:123.123.123.123",
            "::0:0:0:0:0:0:0",
            "::0:0:0:0:0:0",
            "::0:0:0:0:0",
            "::0:0:0:0",
            "::0:0:0",
            "::0:0",
            "::0",
            "0:0:0:0:0:0:0::",
            "0:0:0:0:0:0::",
            "0:0:0:0:0::",
            "0:0:0:0::",
            "0:0:0::",
            "0:0::",
            "0::",
            "0:a:b:c:d:e:f::",
            "::0:a:b:c:d:e:f",
            "a:b:c:d:e:f:0::",
        )

        win32_invalid = {
            "::2:3:4:5:6:7:8",
            "::2222:3333:4444:5555:6666:7777:8888",
            "::2222:3333:4444:5555:6666:123.123.123.123",
            "::0:0:0:0:0:0:0",
            "::0:a:b:c:d:e:f",
        }

        for s in valid:
            if sys.platform == "win32" and s in win32_invalid:
                # socket.inet_pton() on win32 rejects some valid (as
                # far as we can tell) IPv6 addresses.  Skip them.
                continue
            self.assertEqual(
                dns.ipv6.inet_aton(s), socket.inet_pton(socket.AF_INET6, s)
            )

    def test_invalid(self):
        invalid = (
            "",
            ":",
            ":::",
            "2001:DB8:0:0:8:800:200C:417A:221",
            "FF01::101::2",
            "02001:0000:1234:0000:0000:C1C0:ABCD:0876",
            "2001:0000:1234:0000:00001:C1C0:ABCD:0876",
            " 2001:0000:1234:0000:0000:C1C0:ABCD:0876",
            "2001:0000:1234:0000:0000:C1C0:ABCD:0876 ",
            " 2001:0000:1234:0000:0000:C1C0:ABCD:0876  ",
            "2001:0000:1234:0000:0000:C1C0:ABCD:0876  0",
            "2001:0000:1234: 0000:0000:C1C0:ABCD:0876",
            "3ffe:0b00:0000:0001:0000:0000:000a",
            "FF02:0000:0000:0000:0000:0000:0000:0000:0001",
            "3ffe:b00::1::a",
            "::1111:2222:3333:4444:5555:6666::",
            "1:2:3::4:5::7:8",
            "12345::6:7:8",
            "1::5:400.2.3.4",
            "1::5:260.2.3.4",
            "1::5:256.2.3.4",
            "1::5:1.256.3.4",
            "1::5:1.2.256.4",
            "1::5:1.2.3.256",
            "1::5:300.2.3.4",
            "1::5:1.300.3.4",
            "1::5:1.2.300.4",
            "1::5:1.2.3.300",
            "1::5:900.2.3.4",
            "1::5:1.900.3.4",
            "1::5:1.2.900.4",
            "1::5:1.2.3.900",
            "1::5:300.300.300.300",
            "1::5:3000.30.30.30",
            "1::400.2.3.4",
            "1::260.2.3.4",
            "1::256.2.3.4",
            "1::1.256.3.4",
            "1::1.2.256.4",
            "1::1.2.3.256",
            "1::300.2.3.4",
            "1::1.300.3.4",
            "1::1.2.300.4",
            "1::1.2.3.300",
            "1::900.2.3.4",
            "1::1.900.3.4",
            "1::1.2.900.4",
            "1::1.2.3.900",
            "1::300.300.300.300",
            "1::3000.30.30.30",
            "::400.2.3.4",
            "::260.2.3.4",
            "::256.2.3.4",
            "::1.256.3.4",
            "::1.2.256.4",
            "::1.2.3.256",
            "::300.2.3.4",
            "::1.300.3.4",
            "::1.2.300.4",
            "::1.2.3.300",
            "::900.2.3.4",
            "::1.900.3.4",
            "::1.2.900.4",
            "::1.2.3.900",
            "::300.300.300.300",
            "::3000.30.30.30",
            "::1.2.3.4.",
            "2001:1:1:1:1:1:255Z255X255Y255",
            "::ffff:192x168.1.26",
            "::ffff:2.3.4",
            "::ffff:257.1.2.3",
            "1.2.3.4",
            "1.2.3.4:1111:2222:3333:4444::5555",
            "1.2.3.4:1111:2222:3333::5555",
            "1.2.3.4:1111:2222::5555",
            "1.2.3.4:1111::5555",
            "1.2.3.4::5555",
            "1.2.3.4::",
            "fe80:0000:0000:0000:0204:61ff:254.157.241.086",
            "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4",
            "1111:2222:3333:4444:5555:6666:00.00.00.00",
            "1111:2222:3333:4444:5555:6666:000.000.000.000",
            "1111:2222:3333:4444:5555:6666:256.256.256.256",
            "1111:2222:3333:4444::5555:",
            "1111:2222:3333::5555:",
            "1111:2222::5555:",
            "1111::5555:",
            "::5555:",
            "1111:",
            ":1111:2222:3333:4444::5555",
            ":1111:2222:3333::5555",
            ":1111:2222::5555",
            ":1111::5555",
            ":::5555",
            "123",
            "ldkfj",
            "2001::FFD3::57ab",
            "2001:db8:85a3::8a2e:37023:7334",
            "2001:db8:85a3::8a2e:370k:7334",
            "1:2:3:4:5:6:7:8:9",
            "1::2::3",
            "1:::3:4:5",
            "1:2:3::4:5:6:7:8:9",
            "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX",
            "1111:2222:3333:4444:5555:6666:7777:8888:9999",
            "1111:2222:3333:4444:5555:6666:7777:8888::",
            "::2222:3333:4444:5555:6666:7777:8888:9999",
            "1111:2222:3333:4444:5555:6666:7777",
            "1111:2222:3333:4444:5555:6666",
            "1111:2222:3333:4444:5555",
            "1111:2222:3333:4444",
            "1111:2222:3333",
            "1111:2222",
            "1111",
            "11112222:3333:4444:5555:6666:7777:8888",
            "1111:22223333:4444:5555:6666:7777:8888",
            "1111:2222:33334444:5555:6666:7777:8888",
            "1111:2222:3333:44445555:6666:7777:8888",
            "1111:2222:3333:4444:55556666:7777:8888",
            "1111:2222:3333:4444:5555:66667777:8888",
            "1111:2222:3333:4444:5555:6666:77778888",
            "1111:2222:3333:4444:5555:6666:7777:8888:",
            "1111:2222:3333:4444:5555:6666:7777:",
            "1111:2222:3333:4444:5555:6666:",
            "1111:2222:3333:4444:5555:",
            "1111:2222:3333:4444:",
            "1111:2222:3333:",
            "1111:2222:",
            ":8888",
            ":7777:8888",
            ":6666:7777:8888",
            ":5555:6666:7777:8888",
            ":4444:5555:6666:7777:8888",
            ":3333:4444:5555:6666:7777:8888",
            ":2222:3333:4444:5555:6666:7777:8888",
            ":1111:2222:3333:4444:5555:6666:7777:8888",
            ":::2222:3333:4444:5555:6666:7777:8888",
            "1111:::3333:4444:5555:6666:7777:8888",
            "1111:2222:::4444:5555:6666:7777:8888",
            "1111:2222:3333:::5555:6666:7777:8888",
            "1111:2222:3333:4444:::6666:7777:8888",
            "1111:2222:3333:4444:5555:::7777:8888",
            "1111:2222:3333:4444:5555:6666:::8888",
            "::2222::4444:5555:6666:7777:8888",
            "::2222:3333::5555:6666:7777:8888",
            "::2222:3333:4444::6666:7777:8888",
            "::2222:3333:4444:5555::7777:8888",
            "::2222:3333:4444:5555:7777::8888",
            "::2222:3333:4444:5555:7777:8888::",
            "1111::3333::5555:6666:7777:8888",
            "1111::3333:4444::6666:7777:8888",
            "1111::3333:4444:5555::7777:8888",
            "1111::3333:4444:5555:6666::8888",
            "1111::3333:4444:5555:6666:7777::",
            "1111:2222::4444::6666:7777:8888",
            "1111:2222::4444:5555::7777:8888",
            "1111:2222::4444:5555:6666::8888",
            "1111:2222::4444:5555:6666:7777::",
            "1111:2222:3333::5555::7777:8888",
            "1111:2222:3333::5555:6666::8888",
            "1111:2222:3333::5555:6666:7777::",
            "1111:2222:3333:4444::6666::8888",
            "1111:2222:3333:4444::6666:7777::",
            "1111:2222:3333:4444:5555::7777::",
            "1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4",
            "1111:2222:3333:4444:5555:6666:7777:1.2.3.4",
            "1111:2222:3333:4444:5555:6666::1.2.3.4",
            "::2222:3333:4444:5555:6666:7777:1.2.3.4",
            "1111:2222:3333:4444:5555:6666:1.2.3.4.5",
            "1111:2222:3333:4444:5555:1.2.3.4",
            "1111:2222:3333:4444:1.2.3.4",
            "1111:2222:3333:1.2.3.4",
            "1111:2222:1.2.3.4",
            "1111:1.2.3.4",
            "11112222:3333:4444:5555:6666:1.2.3.4",
            "1111:22223333:4444:5555:6666:1.2.3.4",
            "1111:2222:33334444:5555:6666:1.2.3.4",
            "1111:2222:3333:44445555:6666:1.2.3.4",
            "1111:2222:3333:4444:55556666:1.2.3.4",
            "1111:2222:3333:4444:5555:66661.2.3.4",
            "1111:2222:3333:4444:5555:6666:255255.255.255",
            "1111:2222:3333:4444:5555:6666:255.255255.255",
            "1111:2222:3333:4444:5555:6666:255.255.255255",
            ":1.2.3.4",
            ":6666:1.2.3.4",
            ":5555:6666:1.2.3.4",
            ":4444:5555:6666:1.2.3.4",
            ":3333:4444:5555:6666:1.2.3.4",
            ":2222:3333:4444:5555:6666:1.2.3.4",
            ":1111:2222:3333:4444:5555:6666:1.2.3.4",
            ":::2222:3333:4444:5555:6666:1.2.3.4",
            "1111:::3333:4444:5555:6666:1.2.3.4",
            "1111:2222:::4444:5555:6666:1.2.3.4",
            "1111:2222:3333:::5555:6666:1.2.3.4",
            "1111:2222:3333:4444:::6666:1.2.3.4",
            "1111:2222:3333:4444:5555:::1.2.3.4",
            "::2222::4444:5555:6666:1.2.3.4",
            "::2222:3333::5555:6666:1.2.3.4",
            "::2222:3333:4444::6666:1.2.3.4",
            "::2222:3333:4444:5555::1.2.3.4",
            "1111::3333::5555:6666:1.2.3.4",
            "1111::3333:4444::6666:1.2.3.4",
            "1111::3333:4444:5555::1.2.3.4",
            "1111:2222::4444::6666:1.2.3.4",
            "1111:2222::4444:5555::1.2.3.4",
            "1111:2222:3333::5555::1.2.3.4",
            "::.",
            "::..",
            "::...",
            "::1...",
            "::1.2..",
            "::1.2.3.",
            "::.2..",
            "::.2.3.",
            "::.2.3.4",
            "::..3.",
            "::..3.4",
            "::...4",
            ":1111:2222:3333:4444:5555:6666:7777::",
            ":1111:2222:3333:4444:5555:6666::",
            ":1111:2222:3333:4444:5555::",
            ":1111:2222:3333:4444::",
            ":1111:2222:3333::",
            ":1111:2222::",
            ":1111::",
            ":1111:2222:3333:4444:5555:6666::8888",
            ":1111:2222:3333:4444:5555::8888",
            ":1111:2222:3333:4444::8888",
            ":1111:2222:3333::8888",
            ":1111:2222::8888",
            ":1111::8888",
            ":::8888",
            ":1111:2222:3333:4444:5555::7777:8888",
            ":1111:2222:3333:4444::7777:8888",
            ":1111:2222:3333::7777:8888",
            ":1111:2222::7777:8888",
            ":1111::7777:8888",
            ":::7777:8888",
            ":1111:2222:3333:4444::6666:7777:8888",
            ":1111:2222:3333::6666:7777:8888",
            ":1111:2222::6666:7777:8888",
            ":1111::6666:7777:8888",
            ":::6666:7777:8888",
            ":1111:2222:3333::5555:6666:7777:8888",
            ":1111:2222::5555:6666:7777:8888",
            ":1111::5555:6666:7777:8888",
            ":::5555:6666:7777:8888",
            ":1111:2222::4444:5555:6666:7777:8888",
            ":1111::4444:5555:6666:7777:8888",
            ":::4444:5555:6666:7777:8888",
            ":1111::3333:4444:5555:6666:7777:8888",
            ":::3333:4444:5555:6666:7777:8888",
            ":1111:2222:3333:4444:5555::1.2.3.4",
            ":1111:2222:3333:4444::1.2.3.4",
            ":1111:2222:3333::1.2.3.4",
            ":1111:2222::1.2.3.4",
            ":1111::1.2.3.4",
            ":::1.2.3.4",
            ":1111:2222:3333:4444::6666:1.2.3.4",
            ":1111:2222:3333::6666:1.2.3.4",
            ":1111:2222::6666:1.2.3.4",
            ":1111::6666:1.2.3.4",
            ":::6666:1.2.3.4",
            ":1111:2222:3333::5555:6666:1.2.3.4",
            ":1111:2222::5555:6666:1.2.3.4",
            ":1111::5555:6666:1.2.3.4",
            ":::5555:6666:1.2.3.4",
            ":1111:2222::4444:5555:6666:1.2.3.4",
            ":1111::4444:5555:6666:1.2.3.4",
            ":::4444:5555:6666:1.2.3.4",
            ":1111::3333:4444:5555:6666:1.2.3.4",
            "1111:2222:3333:4444:5555:6666:7777:::",
            "1111:2222:3333:4444:5555:6666:::",
            "1111:2222:3333:4444:5555:::",
            "1111:2222:3333:4444:::",
            "1111:2222:3333:::",
            "1111:2222:::",
            "1111:::",
            "1111:2222:3333:4444:5555:6666::8888:",
            "1111:2222:3333:4444:5555::8888:",
            "1111:2222:3333:4444::8888:",
            "1111:2222:3333::8888:",
            "1111:2222::8888:",
            "1111::8888:",
            "::8888:",
            "1111:2222:3333:4444:5555::7777:8888:",
            "1111:2222:3333:4444::7777:8888:",
            "1111:2222:3333::7777:8888:",
            "1111:2222::7777:8888:",
            "1111::7777:8888:",
            "::7777:8888:",
            "1111:2222:3333:4444::6666:7777:8888:",
            "1111:2222:3333::6666:7777:8888:",
            "1111:2222::6666:7777:8888:",
            "1111::6666:7777:8888:",
            "::6666:7777:8888:",
            "1111:2222:3333::5555:6666:7777:8888:",
            "1111:2222::5555:6666:7777:8888:",
            "1111::5555:6666:7777:8888:",
            "::5555:6666:7777:8888:",
            "1111:2222::4444:5555:6666:7777:8888:",
            "1111::4444:5555:6666:7777:8888:",
            "::4444:5555:6666:7777:8888:",
            "1111::3333:4444:5555:6666:7777:8888:",
            "::3333:4444:5555:6666:7777:8888:",
            "::2222:3333:4444:5555:6666:7777:8888:",
            "':10.0.0.1",
        )
        for s in invalid:
            with self.assertRaises(
                dns.exception.SyntaxError, msg=f'invalid IPv6 address: "{s}"'
            ):
                dns.ipv6.inet_aton(s)
