# encoding: utf-8

"""
.. codeauthor:: Tsuyoshi Hombashi <tsuyoshi.hombashi@gmail.com>
"""

import pytest

from tcconfig._common import (
    is_anywhere_network,
    get_anywhere_network,
    get_iproute2_upper_limite_rate,
    get_no_limit_kbits,
    sanitize_network,
)


@pytest.fixture
def device_option(request):
    return request.config.getoption("--device")


class Test_is_anywhere_network(object):

    @pytest.mark.parametrize(["network", "ip_version", "expected"], [
        ["0.0.0.0/0", 4, True],
        ["192.168.0.0/0", 4, False],
        ["::/0", 6, True],
        ["0:0:0:0:0:0:0:0/0", 6, True],
        ["2001:db00::0/24", 6, False],
    ])
    def test_normal(self, network, ip_version, expected):
        assert is_anywhere_network(network, ip_version) == expected

    @pytest.mark.parametrize(["network", "ip_version",  "expected"], [
        [None, 4, ValueError],
        ["0.0.0.0/0", 5, ValueError],
        ["0.0.0.0/0", None, ValueError],
    ])
    def test_exception(self, network, ip_version, expected):
        with pytest.raises(expected):
            is_anywhere_network(network, ip_version)


class Test_get_iproute2_upper_limite_rate(object):

    def test_normal(self):
        assert get_iproute2_upper_limite_rate() == 32000000


class Test_get_anywhere_network(object):

    @pytest.mark.parametrize(["value", "expected"], [
        [4, "0.0.0.0/0"],
        ["4", "0.0.0.0/0"],
        [6, "::/0"],
        ["6", "::/0"],
    ])
    def test_normal(self, value, expected):
        assert get_anywhere_network(value) == expected

    @pytest.mark.parametrize(["value", "expected"], [
        [None, ValueError],
        ["test", ValueError],
    ])
    def test_exception(self, value, expected):
        with pytest.raises(expected):
            get_anywhere_network(value)


class Test_get_no_limit_kbits(object):

    @pytest.mark.parametrize(["speed", "expected"], [
        [1, 1000],
        [0, 0],
    ])
    def test_normal(self, monkeypatch, device_option, speed, expected):
        if device_option is None:
            pytest.skip("device option is null")

        monkeypatch.setattr(
            "tcconfig._common.read_iface_speed", lambda x: speed)

        assert get_no_limit_kbits(device_option) == expected

    @pytest.mark.parametrize(["speed", "expected"], [
        [-1, get_iproute2_upper_limite_rate()],
    ])
    def test_normal_paravirt(
            self, monkeypatch, device_option, speed, expected):
        if device_option is None:
            pytest.skip("device option is null")

        monkeypatch.setattr(
            "tcconfig._common.read_iface_speed", lambda x: speed)

        assert get_no_limit_kbits(device_option) == expected

    @staticmethod
    def raise_ioerror(tc_device):
        raise IOError()

    def test_exception(
            self, monkeypatch, device_option):
        if device_option is None:
            pytest.skip("device option is null")

        monkeypatch.setattr(
            "tcconfig._common.read_iface_speed", self.raise_ioerror)

        assert get_no_limit_kbits(
            device_option) == get_iproute2_upper_limite_rate()


class Test_sanitize_network(object):

    @pytest.mark.parametrize(["value", "ip_version", "expected"], [
        ["192.168.0.1", 4, "192.168.0.1/32"],
        ["192.168.0.1/32", 4, "192.168.0.1/32"],
        ["192.168.0.0/24", 4, "192.168.0.0/24"],
        ["192.168.0.0/23", 4, "192.168.0.0/23"],
        ["2001:db00::0/24", 6, "2001:db00::/24"],
        ["anywhere", 4, "0.0.0.0/0"],
        ["ANYWHERE", 4, "0.0.0.0/0"],
        ["anywhere", 6, "::/0"],
        ["ANYWHERE", 6, "::/0"],
        ["", 4, "0.0.0.0/0"],
        [None, 4, "0.0.0.0/0"],
        ["", 6, "::/0"],
        [None, 6, "::/0"],
    ])
    def test_normal(self, value, ip_version, expected):
        assert sanitize_network(value, ip_version) == expected

    @pytest.mark.parametrize(["value", "ip_version", "expected"], [
        ["192.168.0.1111", 4, ValueError],
        ["192.168.0.", 4, ValueError],
        [".168.0.1", 4, ValueError],
        ["192.168.1.0/23", 4, ValueError],
        ["192.168.0.0/33", 4, ValueError],
        ["192.168.1.0/24", 6, ValueError],
        ["2001:db00::0/24", 4, ValueError],
    ])
    def test_exception(self, value, ip_version, expected):
        with pytest.raises(expected):
            sanitize_network(value, ip_version)
