# SPDX-FileCopyrightText: 2017 Fermi Research Alliance, LLC
# SPDX-License-Identifier: Apache-2.0

import pytest

from decisionengine.framework.modules import Publisher, Source
from decisionengine.framework.modules.Module import verify_products
from decisionengine.framework.modules.Source import Parameter


def test_multiple_consumes_declarations():
    with pytest.raises(Exception, match="@consumes has already been called"):

        @Publisher.consumes(a=int)
        @Publisher.consumes(b=float)
        class _(Publisher.Publisher):
            pass


def test_multiple_produces_declarations():
    with pytest.raises(Exception, match="@produces has already been called"):

        @Source.produces(c=str)
        @Source.produces(d=bool)
        class _(Source.Source):
            pass


def test_wrong_product_names():
    @Source.produces(a=str)
    class BMaker(Source.Source):
        def __init__(self, config):
            super().__init__(config)

        def acquire(self):
            return {"b": ""}

    maker = BMaker({"channel_name": "test"})
    expected_err_msg = (
        "The following products were not produced:\n"
        + " - 'a' of type 'str'\n\n"
        + "The following products were not declared:\n"
        + " - 'b' of type 'str'"
    )
    with pytest.raises(Exception, match=expected_err_msg):
        verify_products(maker, maker.acquire())


def test_wrong_product_types():
    @Source.produces(a=str, b=int)
    class AMaker(Source.Source):
        def __init__(self, config):
            super().__init__(config)

        def acquire(self):
            return {"a": 42, "b": 17}

    maker = AMaker({"channel_name": "test"})
    expected_err_msg = "The following products have the wrong types:\n" + r" - 'a' \(expected 'str', got 'int'\)"
    with pytest.raises(Exception, match=expected_err_msg):
        verify_products(maker, maker.acquire())


def test_supports_config():
    expected_err_msg = (
        "An error occurred while processing the parameter 'conflicting_types':\n"
        + "The specified type 'int' conflicts with the type of the default value "
        + r"'hello' \(type 'str'\)"
    )
    with pytest.raises(Exception, match=expected_err_msg):

        @Source.supports_config(Parameter("conflicting_types", type=int, default="hello"))
        class _(Source.Source):
            pass

[((30, 5, 30, 27), 'decisionengine.framework.modules.Source.produces', 'Source.produces', (), '', False, 'from decisionengine.framework.modules import Publisher, Source\n'), ((50, 5, 50, 34), 'decisionengine.framework.modules.Source.produces', 'Source.produces', (), '', False, 'from decisionengine.framework.modules import Publisher, Source\n'), ((12, 9, 12, 76), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((14, 9, 14, 34), 'decisionengine.framework.modules.Publisher.consumes', 'Publisher.consumes', (), '', False, 'from decisionengine.framework.modules import Publisher, Source\n'), ((15, 9, 15, 36), 'decisionengine.framework.modules.Publisher.consumes', 'Publisher.consumes', (), '', False, 'from decisionengine.framework.modules import Publisher, Source\n'), ((21, 9, 21, 76), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((23, 9, 23, 31), 'decisionengine.framework.modules.Source.produces', 'Source.produces', (), '', False, 'from decisionengine.framework.modules import Publisher, Source\n'), ((24, 9, 24, 32), 'decisionengine.framework.modules.Source.produces', 'Source.produces', (), '', False, 'from decisionengine.framework.modules import Publisher, Source\n'), ((45, 9, 45, 57), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((60, 9, 60, 57), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((70, 9, 70, 57), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((72, 32, 72, 89), 'decisionengine.framework.modules.Source.Parameter', 'Parameter', (), '', False, 'from decisionengine.framework.modules.Source import Parameter\n')]