# Copyright 2017-present Open Networking Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest

import functools
from mock import patch, Mock
import requests_mock

import os
import sys

test_path = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))


def mock_get_westbound_service_instance_properties(props, prop):
    return props[prop]


def match_json(desired, req):
    if desired != req.json():
        raise Exception("Got request %s, but body is not matching" % req.url)
        return False
    return True


class TestSyncFabricCrossconnectServiceInstance(unittest.TestCase):

    def setUp(self):
        global DeferredException

        self.sys_path_save = sys.path

        # Setting up the config module
        from xosconfig import Config
        config = os.path.join(test_path, "../test_fabric_crossconnect_config.yaml")
        Config.clear()
        Config.init(config, "synchronizer-config-schema.yaml")
        # END Setting up the config module

        from xossynchronizer.mock_modelaccessor_build import mock_modelaccessor_config
        mock_modelaccessor_config(test_path, [("fabric-crossconnect", "fabric-crossconnect.xproto"), ])

        import xossynchronizer.modelaccessor
        import mock_modelaccessor
        reload(mock_modelaccessor)  # in case nose2 loaded it in a previous test
        reload(xossynchronizer.modelaccessor)      # in case nose2 loaded it in a previous test

        from xossynchronizer.modelaccessor import model_accessor
        self.model_accessor = model_accessor

        from sync_fabric_crossconnect_service_instance import SyncFabricCrossconnectServiceInstance, model_accessor, \
            DeferredException

        # import all class names to globals
        for (k, v) in model_accessor.all_model_classes.items():
            globals()[k] = v

        self.sync_step = SyncFabricCrossconnectServiceInstance
        self.sync_step.log = Mock()

        # mock onos-fabric
        self.onos_fabric = Service(name="onos-fabric",
                                   rest_hostname="onos-fabric",
                                   rest_port="8181",
                                   rest_username="onos",
                                   rest_password="rocks")

        self.service = FabricCrossconnectService(name="fcservice",
                                                 provider_services=[self.onos_fabric])

    def mock_westbound(self, fsi, s_tag, switch_datapath_id, switch_port):
        # Mock out a ServiceInstance so the syncstep can call get_westbound_service_instance_properties on it
        si = ServiceInstance(id=fsi.id)
        si.get_westbound_service_instance_properties = functools.partial(
            mock_get_westbound_service_instance_properties,
            {"s_tag": s_tag,
             "switch_datapath_id": switch_datapath_id,
             "switch_port": switch_port})
        return si

    def test_format_url(self):
        url = self.sync_step(model_accessor=self.model_accessor).format_url("foo.com/bar")
        self.assertEqual(url, "http://foo.com/bar")

        url = self.sync_step(model_accessor=self.model_accessor).format_url("http://foo.com/bar")
        self.assertEqual(url, "http://foo.com/bar")

    def test_make_handle_extract_handle(self):
        h = self.sync_step(model_accessor=self.model_accessor).make_handle(222, "of:0000000000000201")
        (s_tag, switch_datapath_id) = self.sync_step(model_accessor=self.model_accessor).extract_handle(h)

        self.assertEqual(s_tag, 222)
        self.assertEqual(switch_datapath_id, "of:0000000000000201")

    def test_get_fabric_onos_init(self):
        fsi = FabricCrossconnectServiceInstance(id=7777, owner=self.service)

        d = self.sync_step(model_accessor=self.model_accessor).get_fabric_onos_info(fsi)

        self.assertEqual(d["url"], "http://onos-fabric:8181")
        self.assertEqual(d["user"], "onos")
        self.assertEqual(d["pass"], "rocks")

    def test_range_matches_single(self):
        self.assertTrue(self.sync_step(model_accessor=self.model_accessor).range_matches(123, "123"))

    def test_range_matches_single_incorrect(self):
        self.assertFalse(self.sync_step(model_accessor=self.model_accessor).range_matches(123, "456"))

    def test_range_matches_range(self):
        self.assertTrue(self.sync_step(model_accessor=self.model_accessor).range_matches(123, "122-124"))

    def test_range_matches_range_incorrect(self):
        self.assertFalse(self.sync_step(model_accessor=self.model_accessor).range_matches(123, "110-113"))

    def test_range_matches_any(self):
        self.assertTrue(self.sync_step(model_accessor=self.model_accessor).range_matches(123, "ANY"))
        self.assertTrue(self.sync_step(model_accessor=self.model_accessor).range_matches(123, "any"))

    def test_find_bng_single(self):
        with patch.object(BNGPortMapping.objects, "get_items") as bng_objects, \
                patch.object(self.sync_step, "range_matches") as range_matches:
            bngmapping = BNGPortMapping(s_tag="111", switch_port=4)
            bng_objects.return_value = [bngmapping]

            # this should not be called
            range_matches.return_value = False

            found_bng = self.sync_step(model_accessor=self.model_accessor).find_bng(111)
            self.assertTrue(found_bng)
            self.assertEqual(found_bng.switch_port, 4)

            range_matches.assert_not_called()

    def test_find_bng_any(self):
        with patch.object(BNGPortMapping.objects, "get_items") as bng_objects:
            bngmapping = BNGPortMapping(s_tag="ANY", switch_port=4)
            bng_objects.return_value = [bngmapping]

            found_bng = self.sync_step(model_accessor=self.model_accessor).find_bng(111)
            self.assertTrue(found_bng)
            self.assertEqual(found_bng.switch_port, 4)

    def test_find_bng_range(self):
        with patch.object(BNGPortMapping.objects, "get_items") as bng_objects:
            bngmapping = BNGPortMapping(s_tag="100-200", switch_port=4)
            bng_objects.return_value = [bngmapping]

            found_bng = self.sync_step(model_accessor=self.model_accessor).find_bng(111)
            self.assertTrue(found_bng)
            self.assertEqual(found_bng.switch_port, 4)

    @requests_mock.Mocker()
    def test_sync(self, m):
        with patch.object(ServiceInstance.objects, "get_items") as serviceinstance_objects, \
                patch.object(BNGPortMapping.objects, "get_items") as bng_objects, \
                patch.object(FabricCrossconnectServiceInstance, "save") as fcsi_save:

            fsi = FabricCrossconnectServiceInstance(id=7777, owner=self.service, s_tag=111, source_port=3,
                                                    switch_datapath_id="of:0000000000000201", updated=1, policed=2)

            serviceinstance_objects.return_value = [fsi]

            bngmapping = BNGPortMapping(s_tag="111", switch_port=4)
            bng_objects.return_value = [bngmapping]

            desired_data = {"deviceId": "of:0000000000000201",
                            "vlanId": 111,
                            "endpoints": [3, 4]}

            m.post("http://onos-fabric:8181/onos/segmentrouting/xconnect",
                   status_code=200,
                   additional_matcher=functools.partial(match_json, desired_data))

            self.sync_step(model_accessor=self.model_accessor).sync_record(fsi)
            self.assertTrue(m.called)

            self.assertEqual(fsi.backend_handle, "111/of:0000000000000201")
            fcsi_save.assert_called()

    def test_sync_no_bng_mapping(self):
        with patch.object(ServiceInstance.objects, "get_items") as serviceinstance_objects:

            fsi = FabricCrossconnectServiceInstance(id=7777, owner=self.service, s_tag=111, source_port=3,
                                                    switch_datapath_id="of:0000000000000201", updated=1, policed=2)

            serviceinstance_objects.return_value = [fsi]

            with self.assertRaises(Exception) as e:
                self.sync_step(model_accessor=self.model_accessor).sync_record(fsi)

            self.assertEqual(e.exception.message, "Unable to determine BNG port for s_tag 111")

    def test_sync_not_policed(self):
        with patch.object(ServiceInstance.objects, "get_items") as serviceinstance_objects:

            fsi = FabricCrossconnectServiceInstance(id=7777, owner=self.service, source_port=3,
                                                    switch_datapath_id="of:0000000000000201", updated=1, policed=0)

            serviceinstance_objects.return_value = [fsi]

            with self.assertRaises(Exception) as e:
                self.sync_step(model_accessor=self.model_accessor).sync_record(fsi)

            self.assertEqual(e.exception.message, "Waiting for model_policy to run on fcsi 7777")

    def test_sync_no_s_tag(self):
        with patch.object(ServiceInstance.objects, "get_items") as serviceinstance_objects:

            fsi = FabricCrossconnectServiceInstance(id=7777, owner=self.service, source_port=3,
                                                    switch_datapath_id="of:0000000000000201", updated=1, policed=2)

            serviceinstance_objects.return_value = [fsi]

            with self.assertRaises(Exception) as e:
                self.sync_step(model_accessor=self.model_accessor).sync_record(fsi)

            self.assertEqual(e.exception.message,
                             "Cannot sync FabricCrossconnectServiceInstance if s_tag is None on fcsi 7777")

    def test_sync_no_switch_datapath_id(self):
        with patch.object(ServiceInstance.objects, "get_items") as serviceinstance_objects:

            fsi = FabricCrossconnectServiceInstance(id=7777, owner=self.service, source_port=3, s_tag=111,
                                                    updated=1, policed=2)

            serviceinstance_objects.return_value = [fsi]

            with self.assertRaises(Exception) as e:
                self.sync_step(model_accessor=self.model_accessor).sync_record(fsi)

            self.assertEqual(
                e.exception.message,
                "Cannot sync FabricCrossconnectServiceInstance if switch_datapath_id is unset on fcsi 7777")

    def test_sync_no_source_port(self):
        with patch.object(ServiceInstance.objects, "get_items") as serviceinstance_objects:

            fsi = FabricCrossconnectServiceInstance(id=7777, owner=self.service, s_tag=111,
                                                    switch_datapath_id="of:0000000000000201", updated=1, policed=2)

            serviceinstance_objects.return_value = [fsi]

            with self.assertRaises(Exception) as e:
                self.sync_step(model_accessor=self.model_accessor).sync_record(fsi)

            self.assertEqual(e.exception.message,
                             "Cannot sync FabricCrossconnectServiceInstance if source_port is None on fcsi 7777")

    @requests_mock.Mocker()
    def test_delete(self, m):
        with patch.object(FabricCrossconnectServiceInstance.objects, "get_items") as fcsi_objects:
            fsi = FabricCrossconnectServiceInstance(id=7777, owner=self.service,
                                                    backend_handle="111/of:0000000000000201",
                                                    enacted=True)

            fcsi_objects.return_value = [fsi]

            desired_data = {"deviceId": "of:0000000000000201",
                            "vlanId": 111}

            m.delete("http://onos-fabric:8181/onos/segmentrouting/xconnect",
                     status_code=204,
                     additional_matcher=functools.partial(match_json, desired_data))

            self.sync_step(model_accessor=self.model_accessor).delete_record(fsi)
            self.assertTrue(m.called)

    def tearDown(self):
        self.o = None
        sys.path = self.sys_path_save


if __name__ == '__main__':
    unittest.main()
