# 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 mock
import uuid

from gbpservice.neutron.services.grouppolicy.common import constants
from gbpservice.neutron.services.grouppolicy import config
from gbpservice.neutron.services.grouppolicy.drivers.odl import odl_manager
from gbpservice.neutron.services.grouppolicy.drivers.odl import odl_mapping
from gbpservice.neutron.services.grouppolicy.drivers import resource_mapping
from gbpservice.neutron.services.grouppolicy import plugin as g_plugin
from gbpservice.neutron.tests.unit.services.grouppolicy import (
    test_grouppolicy_plugin as test_plugin)
from neutron.plugins.ml2 import plugin as ml2_plugin
from neutron.tests.unit.ml2 import test_ml2_plugin

TENANT_ID = 'aaaabbbbccccaaaabbbbccccaaaabbbb'
TENANT_UUID = 'aaaabbbb-cccc-aaaa-bbbb-ccccaaaabbbb'

ACTION_1_ID = '1111aaaa-1111-1111-1111-1111bbbb1111'
ACTION_1_NAME = 'fake_name_for_action_1'
ACTION_1_DESC = 'Fake policy action 1'
ACTION_1_TYPE = constants.GP_ACTION_ALLOW

ACTION_2_ID = '1111aaaa-1111-2222-1111-1111bbbb1111'
ACTION_2_NAME = 'fake_name_for_action_2'
ACTION_2_DESC = 'Fake policy action 2'
ACTION_2_TYPE = constants.GP_ACTION_ALLOW

# ACTION_3 is used for negative testing as this action
# is not supported at the moment
ACTION_3_ID = '1111aaaa-1111-3333-1111-1111bbbb1111'
ACTION_3_NAME = 'fake_name_for_action_3'
ACTION_3_DESC = 'Fake policy action 3'
ACTION_3_TYPE = constants.GP_ACTION_REDIRECT

CLASSIFIER_1_ID = '1111aaaa-2222-1111-1111-1111bbbb1111'
CLASSIFIER_1_NAME = 'fake_name_for_classifier_1'
CLASSIFIER_1_DESC = 'Fake policy classifier 1'
CLASSIFIER_1_PROTOCOL = 'tcp'
CLASSIFIER_1_PORT = '321'
CLASSIFIER_1_DIRECTION = 'bi'
CLASSIFIER_1_DEFINITION_ID = '4250ab32-e8b8-445a-aebb-e1bd2cdd291f'

CLASSIFIER_2_ID = '1111aaaa-2222-2222-1111-1111bbbb1111'
CLASSIFIER_2_NAME = 'fake_name_for_classifier_2'
CLASSIFIER_2_DESC = 'Fake policy classifier 2'
CLASSIFIER_2_PROTOCOL = 'tcp'
CLASSIFIER_2_PORT = '123'
CLASSIFIER_2_DIRECTION = 'in'
CLASSIFIER_2_DEFINITION_ID = '4250ab32-e8b8-445a-aebb-e1bd2cdd291f'

CLASSIFIER_3_ID = '1111aaaa-2222-3333-1111-1111bbbb1111'
CLASSIFIER_3_NAME = 'fake_name_for_classifier_3'
CLASSIFIER_3_DESC = 'Fake policy classifier 3'
CLASSIFIER_3_PROTOCOL = 'icmp'
CLASSIFIER_3_DIRECTION = 'bi'
CLASSIFIER_3_DEFINITION_ID = '79c6fdb2-1e1a-4832-af57-c65baf5c2335'

RULE_1_ID = '1111aaaa-3333-1111-1111-1111bbbb1111'
RULE_1_NAME = 'fake_name_for_policy_rule_1'
RULE_1_DESC = 'Fake policy rule 1'

RULE_2_ID = '1111aaaa-3333-2222-1111-1111bbbb1111'
RULE_2_NAME = 'fake_name_for_policy_rule_2'
RULE_2_DESC = 'Fake policy rule 2'

RULE_3_ID = '1111aaaa-3333-3333-1111-1111bbbb1111'
RULE_3_NAME = 'fake_name_for_policy_rule_3'
RULE_3_DESC = 'Fake policy rule 3'

RULE_SET_1_ID = '1111aaaa-4444-1111-1111-1111bbbb1111'
RULE_SET_1_NAME = 'fake_name_for_rule_set_1'
RULE_SET_1_DESC = 'Fake policy rule set 1'

RULE_SET_2_ID = '1111aaaa-4444-2222-1111-1111bbbb1111'
RULE_SET_2_NAME = 'fake_name_for_rule_set_2'
RULE_SET_2_DESC = 'Fake policy rule set 2'

L3P_ID = '2222bbbb-1111-1111-1111-1111cccc1111'
L3P_NAME = 'fake_name_for_l3_policy'
L3P_DESC = 'Fake L3 policy'

NETWORK_ID = '2222bbbb-2222-1111-1111-1111cccc1111'
NETWORK_NAME = 'fake_name_for_network'

L2P_ID = '2222bbbb-3333-1111-1111-1111cccc1111'
L2P_NAME = 'fake_name_for_l2_policy'
L2P_DESC = 'Fake L2 policy'

SUBNET_ID = '2222bbbb-4444-1111-1111-1111cccc1111'
SUBNET_CIDR = '10.10.1.0/24'
SUBNET_GATEWAY_IP = '10.10.1.1'

GROUP_ID = '2222bbbb-5555-1111-1111-1111cccc1111'
GROUP_NAME = 'fake_name_for_ptg'
GROUP_DESC = 'Fake PTG'

PORT_ID = '3333cccc-1111-1111-1111-1111dddd1111'
PORT_MAC = 'fa:33:33:11:11:11'
PORT_IP = '10.10.1.11'
NEUTRON_PORT_ID = 'tap3333cccc-11'

POLICY_TARGET_ID = '3333cccc-2222-1111-1111-1111dddd1111'
POLICY_TARGET_NAME = 'fake_name_for_policy_target'
POLICY_TARGET_DESC = 'Fake Policy Target'

FAKE_CONTEXT = 'fake_context'
FAKE_PLUGIN_CONTEXT = 'fake_plugin_context'

class FakeCorePlugin(object):
    """ A fake plugin to simulate the ML2 plugin

    This plugin provides a minimum set of methods that
    will be used during testing
    """

    def __init__(self):
        self._networks = {}
        self._subnets = {}
        self._ports = {}

    def add_network(self, net_id, net):
        self._networks[net_id] = net

    def get_network(self, plugin_context, net_id):
        return self._networks[net_id]

    def add_subnet(self, subnet_id, subnet):
        self._subnets[subnet_id] = subnet

    def get_subnet(self, plugin_context, subnet_id):
        return self._subnets[subnet_id]

    def add_port(self, port_id, port):
        self._ports[port_id] = port

    def get_port(self, plugin_context, port_id):
        return self._ports[port_id]

class FakeGBPPlugin(object):
    """ A fake plugin to simulate the GBP plugin

    This plugin provides a minimum set of methods that
    will be used during testing
    """

    def __init__(self):
        self._l3ps = {}
        self._l2ps = {}
        self._ptgs = {}
        self._pts = {}
        self._classifiers = {}
        self._actions = {}
        self._rules = {}
        self._rule_sets = {}

    def add_l3_policy(self, l3p_id, l3p):
        self._l3ps[l3p_id] = l3p

    def get_l3_policy(self, plugin_context, l3p_id):
        return self._l3ps[l3p_id]

    def add_l2_policy(self, l2p_id, l2p):
        self._l2ps[l2p_id] = l2p

    def get_l2_policy(self, plugin_context, l2p_id):
        return self._l2ps[l2p_id]

    def add_policy_target_group(self, ptg_id, ptg):
        self._ptgs[ptg_id] = ptg

    def get_policy_target_group(self, plugin_context, ptg_id):
        return self._ptgs[ptg_id]

    def add_policy_target(self, pt_id, pt):
        self._pts[pt_id] = pt

    def get_policy_target(self, plugin_context, pt_id):
        return self._pts[pt_id]

    def add_policy_classifier(self, classifier_id, classifier):
        self._classifiers[classifier_id] = classifier

    def get_policy_classifier(self, plugin_context, classifier_id):
        return self._classifiers[classifier_id]

    def add_policy_action(self, action_id, action):
        self._actions[action_id] = action

    def get_policy_action(self, plugin_context, action_id):
        return self._actions[action_id]

    def add_policy_rule(self, rule_id, rule):
        self._rules[rule_id] = rule

    def get_policy_rule(self, plugin_context, rule_id):
        return self._rules[rule_id]

    def add_policy_rule_set(self, rule_set_id, rule_set):
        self._rule_sets[rule_set_id] = rule_set

    def get_policy_rule_set(self, plugin_context, rule_set_id):
        return self._rule_sets[rule_set_id]

class OdlMappingTestCase(
        test_plugin.GroupPolicyPluginTestCase):
    """ Base test case for ODL mapping driver testing

    Set up the common testing environment
    """

    def setUp(self):
        config.cfg.CONF.set_override('policy_drivers',
                                     ['implicit_policy', 'odl'],
                                     group='group_policy')
        super(OdlMappingTestCase, self).setUp(
            core_plugin=test_ml2_plugin.PLUGIN_NAME)

        self.fake_core_plugin = FakeCorePlugin()
        self.fake_gbp_plugin = FakeGBPPlugin()
        self.driver = odl_mapping.OdlMappingDriver.get_initialized_instance()

        self.fake_gbp_plugin.add_policy_action(
            ACTION_1_ID,
            {
                'id': ACTION_1_ID,
                'tenant_id': TENANT_ID,
                'name': ACTION_1_NAME,
                'description': ACTION_1_DESC,
                'action_type': ACTION_1_TYPE,
            }
        )

        self.fake_gbp_plugin.add_policy_action(
            ACTION_2_ID,
            {
                'id': ACTION_2_ID,
                'tenant_id': TENANT_ID,
                'name': ACTION_2_NAME,
                'description': ACTION_2_DESC,
                'action_type': ACTION_2_TYPE,
            }
        )

        self.fake_gbp_plugin.add_policy_action(
            ACTION_3_ID,
            {
                'id': ACTION_3_ID,
                'tenant_id': TENANT_ID,
                'name': ACTION_3_NAME,
                'description': ACTION_3_DESC,
                'action_type': ACTION_3_TYPE,
            }
        )

        self.fake_gbp_plugin.add_policy_classifier(
            CLASSIFIER_1_ID,
            {
                'id': CLASSIFIER_1_ID,
                'tenant_id': TENANT_ID,
                'name': CLASSIFIER_1_NAME,
                'description': CLASSIFIER_1_DESC,
                'protocol': CLASSIFIER_1_PROTOCOL,
                'port_range': CLASSIFIER_1_PORT,
                'direction': CLASSIFIER_1_DIRECTION
            }
        )

        self.fake_gbp_plugin.add_policy_classifier(
            CLASSIFIER_2_ID,
            {
                'id': CLASSIFIER_2_ID,
                'tenant_id': TENANT_ID,
                'name': CLASSIFIER_2_NAME,
                'description': CLASSIFIER_2_DESC,
                'protocol': CLASSIFIER_2_PROTOCOL,
                'port_range': CLASSIFIER_2_PORT,
                'direction': CLASSIFIER_2_DIRECTION
            }
        )

        self.fake_gbp_plugin.add_policy_classifier(
            CLASSIFIER_3_ID,
            {
                'id': CLASSIFIER_3_ID,
                'tenant_id': TENANT_ID,
                'name': CLASSIFIER_3_NAME,
                'description': CLASSIFIER_3_DESC,
                'protocol': CLASSIFIER_3_PROTOCOL,
                'direction': CLASSIFIER_3_DIRECTION
            }
        )

        self.fake_gbp_plugin.add_policy_rule(
            RULE_1_ID,
            {
                'id': RULE_1_ID,
                'tenant_id': TENANT_ID,
                'name': RULE_1_NAME,
                'description': RULE_1_DESC,
                'policy_classifier_id': CLASSIFIER_1_ID,
                'policy_actions': [ACTION_1_ID]
            }
        )

        self.fake_gbp_plugin.add_policy_rule(
            RULE_2_ID,
            {
                'id': RULE_2_ID,
                'tenant_id': TENANT_ID,
                'name': RULE_2_NAME,
                'description': RULE_2_DESC,
                'policy_classifier_id': CLASSIFIER_2_ID,
                'policy_actions': [ACTION_2_ID]
            }
        )

        self.fake_gbp_plugin.add_policy_rule(
            RULE_3_ID,
            {
                'id': RULE_3_ID,
                'tenant_id': TENANT_ID,
                'name': RULE_3_NAME,
                'description': RULE_3_DESC,
                'policy_classifier_id': CLASSIFIER_1_ID,
                'policy_actions': [ACTION_1_ID, ACTION_2_ID]
            }
        )

        self.fake_gbp_plugin.add_policy_rule_set(
            RULE_SET_1_ID,
            {
                'id': RULE_SET_1_ID,
                'tenant_id': TENANT_ID,
                'name': RULE_SET_1_NAME,
                'description': RULE_SET_1_DESC,
                'policy_rules': [RULE_1_ID]
            }
        )

        self.fake_gbp_plugin.add_policy_rule_set(
            RULE_SET_2_ID,
            {
                'id': RULE_SET_2_ID,
                'tenant_id': TENANT_ID,
                'name': RULE_SET_2_NAME,
                'description': RULE_SET_2_DESC,
                'policy_rules': [RULE_2_ID]
            }
        )

        self.fake_gbp_plugin.add_l3_policy(
            L3P_ID,
            {
                'id': L3P_ID,
                'tenant_id': TENANT_ID,
                'name': L3P_NAME,
                'description': L3P_DESC
            }
        )

        self.fake_core_plugin.add_network(
            NETWORK_ID,
            {
                'id': NETWORK_ID,
                'name': NETWORK_NAME
            }
        )

        self.fake_gbp_plugin.add_l2_policy(
            L2P_ID,
            {
                'id': L2P_ID,
                'tenant_id': TENANT_ID,
                'name': L2P_NAME,
                'description': L2P_DESC,
                'l3_policy_id': L3P_ID,
                'network_id': NETWORK_ID

            }
        )

        self.fake_core_plugin.add_subnet(
            SUBNET_ID,
            {
                'id': SUBNET_ID,
                'cidr': SUBNET_CIDR,
                'network_id': NETWORK_ID,
                'gateway_ip': SUBNET_GATEWAY_IP
            }
        )

        self.fake_gbp_plugin.add_policy_target_group(
            GROUP_ID,
            {
                'id': GROUP_ID,
                'tenant_id': TENANT_ID,
                'name': GROUP_NAME,
                'description': GROUP_DESC,
                'l2_policy_id': L2P_ID,
                'subnets': [SUBNET_ID],
                'provided_policy_rule_sets': [RULE_SET_1_ID],
                'consumed_policy_rule_sets': [RULE_SET_2_ID]
            }
        )

        self.fake_core_plugin.add_port(
            PORT_ID,
            {
                'id': PORT_ID,
                'mac_address': PORT_MAC,
                'fixed_ips': [
                    {
                        'ip_address': PORT_IP,
                        'subnet_id': SUBNET_ID
                    }
                ],
                'network_id': NETWORK_ID
            }
        )

        self.fake_gbp_plugin.add_policy_target(
            POLICY_TARGET_ID,
            {
                'id': POLICY_TARGET_ID,
                'tenant_id': TENANT_ID,
                'name': POLICY_TARGET_NAME,
                'description': POLICY_TARGET_DESC,
                'policy_target_group_id': GROUP_ID,
                'port_id': PORT_ID
            }
        )

class ExternalSegmentTestCase(OdlMappingTestCase):
    """ Test case related with external segment operations

    Currently, ODL cannot handle any external segment operations,
    and should throw an exception in these cases.
    """

    def setUp(self):
        super(ExternalSegmentTestCase, self).setUp()

    def _test_exception_handling(self, method):
        func = getattr(self.driver, method)
        self.assertRaises(
            odl_mapping.ExternalSegmentNotSupportedOnOdlDriver,
            func,
            FAKE_CONTEXT
        )

    def test_create_external_segment_precommit(self):
        self._test_exception_handling('create_external_segment_precommit')

    def test_update_external_segment_precommit(self):
        self._test_exception_handling('update_external_segment_precommit')

    def test_delete_external_segment_precommit(self):
        self._test_exception_handling('delete_external_segment_precommit')

    def test_create_external_policy_precommit(self):
        self._test_exception_handling('create_external_policy_precommit')

    def test_update_external_policy_precommit(self):
        self._test_exception_handling('update_external_policy_precommit')

    def test_delete_external_policy_precommit(self):
        self._test_exception_handling('delete_external_policy_precommit')

    def test_create_nat_pool_precommit(self):
        self._test_exception_handling('create_nat_pool_precommit')

    def test_update_nat_pool_precommit(self):
        self._test_exception_handling('update_nat_pool_precommit')

    def test_delete_nat_pool_precommit(self):
        self._test_exception_handling('delete_nat_pool_precommit')

class PolicyTargetTestCase(OdlMappingTestCase):
    """ Test case for policy target operations
    """

    def setUp(self):
        super(PolicyTargetTestCase, self).setUp()
        self.context = mock.Mock(
            current=self.fake_gbp_plugin.get_policy_target(
                FAKE_CONTEXT,
                POLICY_TARGET_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )

    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'get_l2_policy')
    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'get_policy_target_group')
    @mock.patch.object(ml2_plugin.Ml2Plugin, 'get_port')
    @mock.patch.object(odl_manager.OdlManager, 'register_endpoints')
    @mock.patch.object(resource_mapping.ResourceMappingDriver,
                  'create_policy_target_postcommit')
    def test_create_policy_target_postcommit(
            self,
            mock_create_policy_target_commit,
            mock_register_endpoints,
            mock_get_port,
            mock_get_policy_target_group,
            mock_get_l2_policy):

        # core_plugin and gbp_plugin are mocked and simulated by
        # the fake core plugin and fake gbp plugin
        mock_get_port.side_effect = self.fake_core_plugin.get_port
        mock_get_policy_target_group.side_effect = (
            self.fake_gbp_plugin.get_policy_target_group)
        mock_get_l2_policy.side_effect = self.fake_gbp_plugin.get_l2_policy
        ep = {
            "endpoint-group": GROUP_ID,
            "l2-context": L2P_ID,
            "l3-address": [
                {
                    "ip-address": PORT_IP,
                    "l3-context": L3P_ID
                }
            ],
            "mac-address": PORT_MAC,
            "port-name": NEUTRON_PORT_ID,
            "tenant": TENANT_UUID
        }

        self.driver.create_policy_target_postcommit(self.context)
        mock_create_policy_target_commit.assert_called_once_with(self.context)
        mock_register_endpoints.assert_called_once_with([ep])

    def test_update_policy_target_precommit(self):
        self.assertRaises(
            odl_mapping.UpdatePTNotSupportedOnOdlDriver,
            getattr(self.driver, 'update_policy_target_precommit'),
            self.context
        )

    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'get_l2_policy')
    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'get_policy_target_group')
    @mock.patch.object(ml2_plugin.Ml2Plugin, 'get_port')
    @mock.patch.object(odl_manager.OdlManager, 'unregister_endpoints')
    @mock.patch.object(resource_mapping.ResourceMappingDriver,
                       'delete_policy_target_postcommit')
    def test_delete_policy_target_postcommit(
            self,
            mock_delete_policy_target_commit,
            mock_unregister_endpoints,
            mock_get_port,
            mock_get_policy_target_group,
            mock_get_l2_policy):

        # core_plugin and gbp_plugin are mocked and simulated by
        # the fake core plugin and fake gbp plugin
        mock_get_port.side_effect = self.fake_core_plugin.get_port
        mock_get_policy_target_group.side_effect = (
            self.fake_gbp_plugin.get_policy_target_group)
        mock_get_l2_policy.side_effect = self.fake_gbp_plugin.get_l2_policy
        ep = {
            "l2": [
                {
                    "l2-context": L2P_ID,
                    "mac-address": PORT_MAC
                }
            ],
            "l3": [
                {
                    "ip-address": PORT_IP,
                    "l3-context": L3P_ID
                }
            ],
        }

        self.driver.delete_policy_target_postcommit(self.context)
        mock_delete_policy_target_commit.assert_called_once_with(self.context)
        mock_unregister_endpoints.assert_called_once_with([ep])

class L3PolicyTestCase(OdlMappingTestCase):
    """ Test case for L3 policy operations
    """

    def setUp(self):
        super(L3PolicyTestCase, self).setUp()
        self.context = mock.Mock(
            current=self.fake_gbp_plugin.get_l3_policy(
                FAKE_CONTEXT,
                L3P_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )

    @mock.patch.object(odl_manager.OdlManager, 'create_update_l3_context')
    def test_create_l3_policy_postcommit(
            self,
            mock_create_update_l3_context):

        l3ctx = {
            "id": L3P_ID,
            "name": L3P_NAME,
            "description": L3P_DESC
        }

        self.driver.create_l3_policy_postcommit(self.context)
        mock_create_update_l3_context.assert_called_once_with(
            TENANT_UUID, l3ctx)

    def test_update_l3_policy_precommit(self):
        self.assertRaises(
            odl_mapping.UpdateL3PolicyNotSupportedOnOdlDriver,
            getattr(self.driver, 'update_l3_policy_precommit'),
            self.context
        )

    @mock.patch.object(odl_manager.OdlManager, 'delete_l3_context')
    def test_delete_l3_policy_postcommit(
            self,
            mock_delete_l3_context):

        l3ctx = {
            "id": L3P_ID,
        }

        self.driver.delete_l3_policy_postcommit(self.context)
        mock_delete_l3_context.assert_called_once_with(TENANT_UUID, l3ctx)

class L2PolicyTestCase(OdlMappingTestCase):
    """ Test case for L2 policy operations
    """
    def setUp(self):
        super(L2PolicyTestCase, self).setUp()
        self.context = mock.Mock(
            current=self.fake_gbp_plugin.get_l2_policy(
                FAKE_CONTEXT,
                L2P_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )

    @mock.patch.object(ml2_plugin.Ml2Plugin, 'get_network')
    @mock.patch.object(odl_manager.OdlManager,
                       'create_update_l2_flood_domain')
    @mock.patch.object(odl_manager.OdlManager,
                       'create_update_l2_bridge_domain')
    @mock.patch.object(resource_mapping.ResourceMappingDriver,
                       'create_l2_policy_postcommit')
    def test_create_l2_policy_postcommit(
            self,
            mock_create_l2_policy_postcommit,
            mock_create_update_l2_bridge_domain,
            mock_create_update_l2_flood_domain,
            mock_get_network):

        # core_plugin is mocked and simulated by the fake core plugin
        mock_get_network.side_effect = self.fake_core_plugin.get_network
        l2bd = {
            "id": L2P_ID,
            "name": L2P_NAME,
            "description": L2P_DESC,
            "parent": L3P_ID
        }
        l2fd = {
            "id": NETWORK_ID,
            "name": NETWORK_NAME,
            "parent": L2P_ID
        }

        self.driver.create_l2_policy_postcommit(self.context)
        mock_create_l2_policy_postcommit.assert_called_once_with(self.context)
        mock_create_update_l2_bridge_domain.assert_called_once_with(
            TENANT_UUID, l2bd)
        mock_create_update_l2_flood_domain.assert_called_with(TENANT_UUID,
                                                              l2fd)

    def test_update_l2_policy_precommit(self):
        self.assertRaises(
            odl_mapping.UpdateL2PolicyNotSupportedOnOdlDriver,
            getattr(self.driver, 'update_l2_policy_precommit'),
            self.context
        )

    @mock.patch.object(odl_manager.OdlManager, 'delete_l2_flood_domain')
    @mock.patch.object(odl_manager.OdlManager, 'delete_l2_bridge_domain')
    @mock.patch.object(resource_mapping.ResourceMappingDriver,
                       'delete_l2_policy_postcommit')
    def test_delete_l2_policy_postcommit(
            self,
            mock_delete_l2_policy_postcommit,
            mock_delete_l2_bridge_domain,
            mock_delete_l2_flood_domain):

        l2bd = {
            "id": L2P_ID,
        }
        l2fd = {
            "id": NETWORK_ID,
        }

        self.driver.delete_l2_policy_postcommit(self.context)
        mock_delete_l2_policy_postcommit.assert_called_once_with(self.context)
        mock_delete_l2_bridge_domain.assert_called_once_with(TENANT_UUID,
                                                             l2bd)
        mock_delete_l2_flood_domain.assert_called_with(TENANT_UUID, l2fd)

class PolicyTargetGroupTestCase(OdlMappingTestCase):
    """ Test case for policy target group operations
    """

    def setUp(self):
        super(PolicyTargetGroupTestCase, self).setUp()
        self.context = mock.Mock(
            current=self.fake_gbp_plugin.get_policy_target_group(
                FAKE_CONTEXT,
                GROUP_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )

    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'get_policy_action')
    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'get_policy_classifier')
    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'get_policy_rule')
    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'get_policy_rule_set')
    @mock.patch.object(ml2_plugin.Ml2Plugin, 'get_subnet')
    @mock.patch.object(odl_manager.OdlManager, 'create_update_subnet')
    @mock.patch.object(odl_manager.OdlManager, 'create_update_endpoint_group')
    @mock.patch.object(odl_manager.OdlManager, 'create_update_contract')
    @mock.patch.object(resource_mapping.ResourceMappingDriver,
                       'create_policy_target_group_postcommit')
    def test_create_policy_target_postcommit(
            self,
            mock_create_policy_target_group_postcommit,
            mock_create_update_contract,
            mock_create_update_endpoint_group,
            mock_create_update_subnet,
            mock_get_subnet,
            mock_get_policy_rule_set,
            mock_get_policy_rule,
            mock_get_policy_classifier,
            mock_get_policy_action):

        # core_plugin and gbp_plugin are mocked and simulated by
        # the fake core plugin and fake gbp plugin
        mock_get_subnet.side_effect = self.fake_core_plugin.get_subnet
        mock_get_policy_rule_set.side_effect = (self.fake_gbp_plugin.
                                                get_policy_rule_set)
        mock_get_policy_rule.side_effect = (self.fake_gbp_plugin.
                                            get_policy_rule)
        mock_get_policy_classifier.side_effect = (self.fake_gbp_plugin.
                                                  get_policy_classifier)
        mock_get_policy_action.side_effect = (self.fake_gbp_plugin.
                                              get_policy_action)

        provided_contract_id = (
            uuid.uuid3(uuid.NAMESPACE_DNS, RULE_SET_1_NAME).urn[9:])
        provided_contract = {
            "id": provided_contract_id,
            "clause": [
                {
                    "name": RULE_SET_1_NAME,
                    "subject-refs": [RULE_SET_1_NAME]
                }
            ],
            "subject": [
                {
                    "name": RULE_SET_1_NAME,
                    "rule": [
                        {
                            "name": RULE_1_NAME,
                            "classifier-ref": [
                                {
                                    "name": CLASSIFIER_1_NAME + '-sourceport'
                                },
                                {
                                    "name": CLASSIFIER_1_NAME + '-destport'
                                }
                            ]
                        }

                    ]
                }
            ]
        }
        consumed_contract_id = (
            uuid.uuid3(uuid.NAMESPACE_DNS, RULE_SET_2_NAME).urn[9:])
        consumed_contract = {
            "id": consumed_contract_id,
            "clause": [
                {
                    "name": RULE_SET_2_NAME,
                    "subject-refs": [RULE_SET_2_NAME]
                }
            ],
            "subject": [
                {
                    "name": RULE_SET_2_NAME,
                    "rule": [
                        {
                            "name": RULE_2_NAME,
                            "classifier-ref": [
                                {
                                    "name": CLASSIFIER_2_NAME + '-sourceport',
                                    "direction": 'out'
                                },
                                {
                                    "name": CLASSIFIER_2_NAME + '-destport',
                                    "direction": 'in'
                                },
                            ]
                        }

                    ]
                }
            ]
        }
        epg = {
            "id": GROUP_ID,
            "name": GROUP_NAME,
            "network-domain": SUBNET_ID,
            "provider-named-selector": {
                "name": 'Contract-' + provided_contract_id,
                "contract": provided_contract_id
            },
            "consumer-named-selector": {
                "name": 'Contract-' + consumed_contract_id,
                "contract": consumed_contract_id
            }
        }
        odl_subnet = {
            "id": SUBNET_ID,
            "ip-prefix": SUBNET_CIDR,
            "parent": NETWORK_ID,
            "virtual-router-ip": SUBNET_GATEWAY_IP
        }

        self.driver.create_policy_target_group_postcommit(self.context)
        mock_create_policy_target_group_postcommit.assert_called_once_with(
            self.context)
        mock_create_update_contract.assert_any_call(TENANT_UUID,
                                                    provided_contract)
        mock_create_update_contract.assert_any_call(TENANT_UUID,
                                                    consumed_contract)
        mock_create_update_endpoint_group.assert_called_once_with(TENANT_UUID,
                                                                  epg)
        mock_create_update_subnet.assert_called_once_with(TENANT_UUID,
                                                          odl_subnet)

    def test_update_policy_target_group_precommit(self):
        self.assertRaises(
            odl_mapping.UpdatePTGNotSupportedOnOdlDriver,
            getattr(self.driver, 'update_policy_target_group_precommit'),
            self.context
        )

    @mock.patch.object(odl_mapping.OdlMappingDriver, '_cleanup_subnet')
    @mock.patch.object(odl_manager.OdlManager, 'delete_endpoint_group')
    @mock.patch.object(odl_manager.OdlManager, 'delete_subnet')
    def test_delete_policy_target_group_postcommit(
            self,
            mock_delete_subnet,
            mock_delete_endpoint_group,
            mock__cleanup_subnet):

        odl_subnet = {
            "id": SUBNET_ID
        }
        epg = {
            "id": GROUP_ID
        }

        self.driver.delete_policy_target_group_postcommit(self.context)
        mock_delete_subnet.assert_called_once_with(TENANT_UUID, odl_subnet)
        mock_delete_endpoint_group.assert_called_once_with(TENANT_UUID, epg)
        mock__cleanup_subnet.assert_called_once_with(
            self.context._plugin_context, SUBNET_ID, None)

class PolicyActionTestCase(OdlMappingTestCase):
    """ Test case for policy action operations
    """

    def setUp(self):
        super(PolicyActionTestCase, self).setUp()
        self.context_1 = mock.Mock(
            current=self.fake_gbp_plugin.get_policy_action(
                FAKE_CONTEXT,
                ACTION_1_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )
        self.context_3 = mock.Mock(
            current=self.fake_gbp_plugin.get_policy_action(
                FAKE_CONTEXT,
                ACTION_3_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )

    def test_create_policy_action_precommit(self):
        # No exception should be raised
        self.driver.create_policy_action_precommit(self.context_1)

        # Exception should be raised only when ACTION is redirect
        self.assertRaises(
            odl_mapping.RedirectActionNotSupportedOnOdlDriver,
            getattr(self.driver, 'create_policy_action_precommit'),
            self.context_3
        )

    @mock.patch.object(resource_mapping.ResourceMappingDriver,
                       'create_policy_action_postcommit')
    def test_create_policy_action_postcommit(
            self,
            mock_create_policy_action_postcommit):

        # Exception should be raised only when ACTION is redirect
        self.driver.create_policy_action_postcommit(self.context_1)
        mock_create_policy_action_postcommit.assert_called_once_with(
            self.context_1)
        self.assertRaises(
            odl_mapping.OnlyAllowActionSupportedOnOdlDriver,
            getattr(self.driver, 'create_policy_action_postcommit'),
            self.context_3
        )

    def test_update_policy_action_precommit(self):
        self.assertRaises(
            odl_mapping.UpdatePolicyActionNotSupportedOnOdlDriver,
            getattr(self.driver, 'update_policy_action_precommit'),
            self.context_1
        )

    @mock.patch.object(resource_mapping.ResourceMappingDriver,
                       'delete_policy_action_postcommit')
    def test_delete_policy_action_postcommit(
            self,
            mock_delete_policy_action_postcommit):
        self.driver.delete_policy_action_postcommit(self.context_1)
        mock_delete_policy_action_postcommit.assert_called_once_with(
            self.context_1)

class PolicyClassifierTestCase(OdlMappingTestCase):
    """ Test case for policy classifier operations
    """

    def setUp(self):
        super(PolicyClassifierTestCase, self).setUp()
        self.context_1 = mock.Mock(
            current=self.fake_gbp_plugin.get_policy_classifier(
                FAKE_CONTEXT,
                CLASSIFIER_1_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )
        self.context_3 = mock.Mock(
            current=self.fake_gbp_plugin.get_policy_classifier(
                FAKE_CONTEXT,
                CLASSIFIER_3_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )

    @mock.patch.object(odl_manager.OdlManager, 'create_classifier')
    def test_create_policy_classifier_postcommit(
            self,
            mock_create_classifier):

        # Ensure two classifiers are created in ODL for TCP
        classifier_instance_1_dest = {
            "classifier-definition-id": CLASSIFIER_1_DEFINITION_ID,
            "name": CLASSIFIER_1_NAME + "-destport",
            "parameter-value": [
                {
                    "name": "type",
                    "string-value": CLASSIFIER_1_PROTOCOL
                },
                {
                    "name": "destport",
                    "int-value": CLASSIFIER_1_PORT
                }
            ]
        }
        classifier_instance_1_source = {
            "classifier-definition-id": CLASSIFIER_1_DEFINITION_ID,
            "name": CLASSIFIER_1_NAME + "-sourceport",
            "parameter-value": [
                {
                    "name": "type",
                    "string-value": CLASSIFIER_1_PROTOCOL
                },
                {
                    "name": "sourceport",
                    "int-value": CLASSIFIER_1_PORT
                }
            ]
        }
        self.driver.create_policy_classifier_postcommit(self.context_1)
        mock_create_classifier.assert_any_call(TENANT_UUID,
                                               classifier_instance_1_source)
        mock_create_classifier.assert_any_call(TENANT_UUID,
                                               classifier_instance_1_dest)
        mock_create_classifier.reset_mock()

        # only one classifier for ICMP
        classifier_instance_3 = {
            "classifier-definition-id": CLASSIFIER_3_DEFINITION_ID,
            "name": CLASSIFIER_3_NAME,
            "parameter-value": [
                {
                    "name": "proto",
                    "int-value": 1
                }
            ]
        }
        self.driver.create_policy_classifier_postcommit(self.context_3)
        mock_create_classifier.assert_called_once_with(TENANT_UUID,
                                                       classifier_instance_3)

    def test_update_policy_classifier_precommit(self):
        self.assertRaises(
            odl_mapping.UpdateClassifierNotSupportedOnOdlDriver,
            getattr(self.driver, 'update_policy_classifier_precommit'),
            self.context_1
        )

    @mock.patch.object(odl_manager.OdlManager, 'delete_classifier')
    def test_delete_policy_classifier_postcommit(
            self,
            mock_delete_classifier):

        # Ensure both classifiers are deleted for TCP/UDP
        classifier_instance_1_dest = {
            "name": CLASSIFIER_1_NAME + "-destport"
        }
        classifier_instance_1_source = {
            "name": CLASSIFIER_1_NAME + "-sourceport"
        }
        self.driver.delete_policy_classifier_postcommit(self.context_1)
        mock_delete_classifier.assert_any_call(TENANT_UUID,
                                               classifier_instance_1_source)
        mock_delete_classifier.assert_any_call(TENANT_UUID,
                                               classifier_instance_1_dest)
        mock_delete_classifier.reset_mock()

        # Ensure only one classifier is deleted for ICMP
        classifier_instance_3 = {
            "name": CLASSIFIER_3_NAME,
        }
        self.driver.delete_policy_classifier_postcommit(self.context_3)
        mock_delete_classifier.assert_called_once_with(TENANT_UUID,
                                                       classifier_instance_3)

class PolicyRuleTestCase(OdlMappingTestCase):
    """ Test case for policy rule operations
    """
    def setUp(self):
        super(PolicyRuleTestCase, self).setUp()
        self.context_1 = mock.Mock(
            current=self.fake_gbp_plugin.get_policy_rule(
                FAKE_CONTEXT,
                RULE_1_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )
        self.context_3 = mock.Mock(
            current=self.fake_gbp_plugin.get_policy_rule(
                FAKE_CONTEXT,
                RULE_3_ID
            ),
            _plugin_context=FAKE_PLUGIN_CONTEXT,
            _plugin=self.fake_gbp_plugin
        )

    def test_create_policy_rule_precommit(self):
        # No exception should be raised
        self.driver.create_policy_rule_precommit(self.context_1)

        # Ensure exception be raised only when multiple actions appear
        self.assertRaises(
            odl_mapping.ExactlyOneActionPerRuleIsSupportedOnOdlDriver,
            getattr(self.driver, 'create_policy_rule_precommit'),
            self.context_3
        )

    def test_update_policy_rule_precommit(self):
        self.assertRaises(
            odl_mapping.PolicyRuleUpdateNotSupportedOnOdlDriver,
            getattr(self.driver, 'update_policy_rule_precommit'),
            self.context_1
        )

class DHCPTestCase(OdlMappingTestCase):
    """ Test case for DHCP related operations
    """

    def setUp(self):
        super(DHCPTestCase, self).setUp()
        mock_sql = mock.Mock()
        mock_sql.query.return_value = mock_sql
        mock_sql.join.return_value = mock_sql
        mock_sql.filter.return_value = mock_sql
        mock_sql.first.return_value = {
            "id": GROUP_ID,
            "name": GROUP_NAME
        }
        self.plugin_context = mock.Mock(
            session=mock_sql
        )
        self.port = {
            "id": PORT_ID,
            "network_id": NETWORK_ID,
            "tenant_id": TENANT_ID
        }

    @mock.patch.object(g_plugin.GroupPolicyPlugin, 'create_policy_target')
    @mock.patch.object(odl_mapping.OdlMappingDriver, '_port_is_owned')
    @mock.patch.object(ml2_plugin.Ml2Plugin, '_get_subnets_by_network')
    def test_create_dhcp_policy_target_if_needed(
            self,
            mock_get_subnets_by_network,
            mock_port_is_owned,
            mock_create_policy_target):

        mock_get_subnets_by_network.return_value = [
            {
                "id": SUBNET_ID
            }
        ]
        attrs = {
            "policy_target": {
                "tenant_id": TENANT_ID,
                "name": 'dhcp-' + GROUP_ID,
                "description": "Implicitly created DHCP policy target",
                "policy_target_group_id": GROUP_ID,
                "port_id": PORT_ID
            }
        }

        # Test that gbp_plugin.create_policy_target was NOT called
        mock_port_is_owned.return_value = True
        self.driver.create_dhcp_policy_target_if_needed(self.plugin_context,
                                                        self.port)
        self.assertFalse(mock_create_policy_target.called,
                         'Failed not to create DHCP PT when not needed')

        # Test that gbp_plugin.create_policy_target was called indeed
        mock_port_is_owned.return_value = False
        self.driver.create_dhcp_policy_target_if_needed(self.plugin_context,
                                                        self.port)
        mock_create_policy_target.assert_called_once_with(self.plugin_context,
                                                          attrs)


import json
import argparse
import os

from . import utils as mllogger
import mlperf_logging.mllog as mllog

# map keys traditionally used in hugectr configs
# to more descriptive ones more suitable for MLPerf
hugectr_to_mlperf_layer_name = {
    'sparse_embedding1': 'embeddings',
    'fc1': 'bottom_mlp_dense1',
    'fc2': 'bottom_mlp_dense2',
    'fc3': 'bottom_mlp_dense3',
    'fc4': 'top_mlp_dense1',
    'fc5': 'top_mlp_dense2',
    'fc6': 'top_mlp_dense3',
    'fc7': 'top_mlp_dense4',
    'fc8': 'top_mlp_dense5'
}

def log_hparams(config):
    mllogger.log_event(key='eval_samples',
                       value=config['layers'][0]['eval_num_samples'])
    mllogger.log_event(key='global_batch_size',
                       value=config['solver']['batchsize'])
    mllogger.log_event(key='opt_base_learning_rate',
                       value=config['optimizer']['sgd_hparam']['learning_rate'])
    mllogger.log_event(key='sgd_opt_base_learning_rate',
                       value=config['optimizer']['sgd_hparam']['learning_rate'])
    mllogger.log_event(key='sgd_opt_learning_rate_decay_poly_power',
                       value=config['optimizer']['sgd_hparam'].get('decay_power'))
    mllogger.log_event(key='opt_learning_rate_warmup_steps',
                       value=config['optimizer']['sgd_hparam']['warmup_steps'])
    mllogger.log_event(key='opt_learning_rate_warmup_factor',
                       value=0.0)  # not configurable
    mllogger.log_event(key='lr_decay_start_steps',
                       value=config['optimizer']['sgd_hparam'].get('decay_start'))
    mllogger.log_event(key='sgd_opt_learning_rate_decay_steps',
                       value=config['optimizer']['sgd_hparam'].get('decay_steps'))
    mllogger.log_event(key='gradient_accumulation_steps',
                       value=1)  # not configurable

def log_config(config):
    # print hparams and submission info on the first node only
    if 'SLURM_NODEID' not in os.environ or os.environ['SLURM_NODEID'] == '0':
        mllogger.mlperf_submission_log('dlrm')
        log_hparams(config)

    for layer in config['layers']:
        hugectr_name = layer['name']
        if hugectr_name not in hugectr_to_mlperf_layer_name:
            # layer has no parameters, nothing to be done
            continue

        mlperf_name = hugectr_to_mlperf_layer_name[hugectr_name]
        mllogger.log_event(mllog.constants.WEIGHTS_INITIALIZATION,
                           metadata={'tensor': mlperf_name})

class LogConverter:
    def __init__(self, steps_per_epoch, start_timestamp):
        self.start_time = start_timestamp
        self.steps_per_epoch = steps_per_epoch

    def _get_log_foo(self, key):
        if '_start' in key:
            return mllogger.log_start
        if '_end' in key or '_stop' in key:
            return mllogger.log_end
        else:
            return mllogger.log_event

    def _get_value(self, data):
        if data[0] == 'eval_accuracy':
            return float(data[1])
        if data[0] == 'train_samples':
            return int(data[1])

    def _get_metadata(self, data):
        if data[0] == 'eval_accuracy':
            self._last_eval_accuracy = float(data[1])
            return { 'epoch_num': float(data[2]) + 1 }
        if 'eval' in data[0]:
            return { 'epoch_num': float(data[1]) + 1 }
        if 'epoch' in data[0]:
            return { 'epoch_num': int(data[1]) + 1 }
        if data[0] == 'run_stop':
            return { 'status': 'success' if self._last_eval_accuracy > 0.8025 else 'aborted' }

    def _get_kvm(self, data):
        key = data[0]
        if data[0] == 'init_end':
            key = 'init_stop'
        if data[0] == 'train_epoch_start':
            key = 'epoch_start'
        if data[0] == 'train_epoch_end':
            key = 'epoch_stop'

        value = self._get_value(data)
        metadata = self._get_metadata(data)

        return key, value, metadata

    def _get_time_ms(self, ms):
        return self.start_time + int(float(ms))

    def validate_event(self, event):
        try:
            float(event[0])

            if not event[1].isidentifier():
                return False

            for x in event[2:]:
                float(x)
            return True
        except:
            return False

    def log_throughput(self, line):
        """Read throughput from log file of recommendation

        Example:
            From Below line
            "Hit target accuracy AUC 0.8025 at epoch 0.95 in 22718s. Average speed 175427.7 records/s."
            Get the value -> 175427.7
        """
        lastmatch = None
        if "Hit target accuracy" in line:
            lastmatch = line
        elif "Average speed" in line:
            lastmatch = line
        throughput = 0

        if lastmatch is not None:
            throughput = float(lastmatch.split(' ')[-2])
            epoch = float(lastmatch.split(' ')[7])

        if throughput > 0:
            mllogger.log_event(key="tracked_stats",
                               value={'throughput': throughput},
                               metadata={'step': epoch})

    def log_event(self, event_log):
        if self.validate_event(event_log):
            log_foo = self._get_log_foo(event_log[1])
            key, value, metadata = self._get_kvm(event_log[1:])
            time_ms = self._get_time_ms(event_log[0])

            log_foo(key=key, value=value, metadata=metadata, time_ms=time_ms)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--log_path', type=str,
                        help='Path to the logs to be translated')

    parser.add_argument('--config_file', type=str,
                        help='HugeCTR input config file in JSON format')

    parser.add_argument('--start_timestamp', type=int,
                        help='Seconds since 1970-01-01 00:00:00 UTC at the time of training start')
    args = parser.parse_args()

    with open(args.config_file, 'r') as f:
        config = json.load(f)
    log_config(config)

    # Convert to ms to be consistent with the MLPerf logging API
    start_timestamp_ms = args.start_timestamp * 1000
    converter = LogConverter(
        steps_per_epoch=(config['layers'][0]['num_samples'] / config['solver']['batchsize']),
        start_timestamp=start_timestamp_ms,
    )

    with open(args.log_path) as f:
        log_lines = f.readlines()

    for line in log_lines:
        event_log = [x.strip() for x in line.strip().strip('][\x08 ,').split(',')]
        converter.log_event(event_log)
        converter.log_throughput(line)

if __name__ == '__main__':
    main()


from django import forms
from .models import Post

class CommentForm(forms.Form):
    username = forms.CharField(
        error_messages={
            'required':"you shold Enter a user name :O"
        },
        help_text="this name is important"
    )
    comment = forms.CharField(
        widget=forms.Textarea,
        min_length= 100,
        error_messages={
            'required':"Haaaa ",
            'min_length':"you need more space yah!!"
        }
    )

class CreatePost(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'description', 'categories', 'author']


# -*- coding: utf-8 -*- #
# Copyright 2015 Google Inc. All Rights Reserved.
#
# 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.
"""Tests of the datastore_util module."""

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import os
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.command_lib.emulators import datastore_util
from googlecloudsdk.command_lib.emulators import util
from googlecloudsdk.core import execution_utils
from googlecloudsdk.core import properties
from tests.lib import sdk_test_base
from tests.lib import test_case
import mock

class DatastoreUtilTests(sdk_test_base.WithFakeAuth):

  def SetUp(self):
    properties.VALUES.core.project.Set(self.Project())

  def Project(self):
    return 'fake-project'

  def testGetLegacyGCDRoot(self):
    self._DoTestGetGCDRoot('gcd', True)

  def testGetGCDRoot(self):
    self._DoTestGetGCDRoot('cloud-datastore-emulator', False)

  def _DoTestGetGCDRoot(self, gcd_dir, legacy):
    cloud_sdk_mock = self.StartObjectPatch(util, 'GetCloudSDKRoot')
    cloud_sdk_mock.return_value = 'pathtocloudsdk'

    os_isdir_mock = self.StartObjectPatch(os.path, 'isdir')
    os_isdir_mock.return_value = True
    args = type(str('args_mock'),
                (object,),
                dict(legacy=legacy))

    expected = os.path.join(cloud_sdk_mock.return_value, 'platform', gcd_dir)
    self.assertEqual(expected, datastore_util.GetGCDRoot(args))

    os_isdir_mock.return_value = False
    with self.assertRaises(datastore_util.NoGCDError):
      datastore_util.GetGCDRoot(args)

  @test_case.Filters.DoNotRunOnWindows
  def testArgsForLegacyGCDEmulatorOnNonWindows(self):
    self._DoTestArgsForGCDEmulatorOnNonWindows('gcd.sh', True)

  @test_case.Filters.DoNotRunOnWindows
  def testArgsForGCDEmulatorOnNonWindows(self):
    self._DoTestArgsForGCDEmulatorOnNonWindows('cloud_datastore_emulator',
                                               False)

  def _DoTestArgsForGCDEmulatorOnNonWindows(self, gcd_exec, legacy):
    gcd_root_mock = self.StartObjectPatch(datastore_util, 'GetGCDRoot')
    gcd_root_mock.return_value = 'pathtogcdroot'
    args = type(str('args_mock'),
                (object,),
                dict(legacy=legacy))

    gcd_executable = os.path.join(gcd_root_mock.return_value, gcd_exec)
    self.assertEqual(execution_utils.ArgsForExecutableTool(gcd_executable,
                                                           'args'),
                     datastore_util.ArgsForGCDEmulator(['args'], args))

  @test_case.Filters.RunOnlyOnWindows
  def testArgsForLegacyGCDEmulatorWindows(self):
    self._DoTestArgsForGCDEmulatorWindows('gcd.cmd', True)

  @test_case.Filters.RunOnlyOnWindows
  def testArgsForGCDEmulatorWindows(self):
    self._DoTestArgsForGCDEmulatorWindows('cloud_datastore_emulator.cmd',
                                          False)

  def _DoTestArgsForGCDEmulatorWindows(self, gcd_exec, legacy):
    gcd_root_mock = self.StartObjectPatch(datastore_util, 'GetGCDRoot')
    gcd_root_mock.return_value = 'pathtogcdroot'

    args = type(str('args_mock'),
                (object,),
                dict(legacy=legacy))

    gcd_executable = os.path.join(gcd_root_mock.return_value, gcd_exec)
    self.assertEqual(execution_utils.ArgsForCMDTool(gcd_executable, 'args'),
                     datastore_util.ArgsForGCDEmulator(['args'], args))

  def testPrepareLegacyGCDDataDir(self):
    self._DoTestPrepareGCDDataDir(True)

  def testPrepareGCDDataDir(self):
    self._DoTestPrepareGCDDataDir(False)

  def _DoTestPrepareGCDDataDir(self, legacy):
    gcd_root_mock = self.StartObjectPatch(datastore_util, 'GetGCDRoot')
    gcd_root_mock.return_value = 'pathtogcdroot'
    exec_mock = self.StartObjectPatch(util, 'Exec')
    process = mock.Mock()
    process.poll.return_value = 0
    exec_mock.return_value.__enter__.return_value = process
    prefix_mock = self.StartObjectPatch(util, 'PrefixOutput')

    data_dir = self.CreateTempDir()
    args = type(str('args_mock'),
                (object,),
                dict(legacy=legacy,
                     data_dir=data_dir))

    # Nothing should be done if data-dir is non-empty
    tmp_file = self.Touch(directory=data_dir)
    datastore_util.PrepareGCDDataDir(args)
    self.assertFalse(exec_mock.called)

    # gcd create should be called if data-dir is empty
    exec_mock.reset_mock()
    prefix_mock.reset_mock()
    os.remove(tmp_file)
    datastore_util.PrepareGCDDataDir(args)
    create_args = ['create',
                   '--project_id={0}'.format(self.Project()),
                   data_dir,]
    exec_args = datastore_util.ArgsForGCDEmulator(create_args, args)
    exec_mock.assert_called_once_with(exec_args)
    prefix_mock.assert_called_once_with(process, 'datastore')

    # gcd create should be called if data-dir does not exist
    exec_mock.reset_mock()
    prefix_mock.reset_mock()
    os.rmdir(data_dir)
    datastore_util.PrepareGCDDataDir(args)
    exec_mock.assert_called_once_with(exec_args)
    prefix_mock.assert_called_once_with(process, 'datastore')

    # Should throw exception if PrepareGCDDataDir fails
    process.poll.return_value = 1
    with self.assertRaises(datastore_util.UnableToPrepareDataDir):
      datastore_util.PrepareGCDDataDir(args)

  def testStartLegacyGCDEmulator(self):
    self._DoTestStartGCDEmulator(True)

  def testStartGCDEmulator(self):
    self._DoTestStartGCDEmulator(False)

  def _DoTestStartGCDEmulator(self, legacy):
    gcd_root_mock = self.StartObjectPatch(datastore_util, 'GetGCDRoot')
    gcd_root_mock.return_value = 'pathtogcdroot'
    exec_mock = self.StartObjectPatch(util, 'Exec')

    args = type(str('args_mock'),
                (object,),
                dict(host_port=arg_parsers.HostPort('localhost', '8080'),
                     store_on_disk=True,
                     data_dir='temp_dir',
                     consistency=0.7,
                     legacy=legacy))
    datastore_util.StartGCDEmulator(args)
    start_args = ['start',
                  '--host=localhost',
                  '--port=8080',
                  '--store_on_disk=True',
                  '--consistency=0.7',
                  '--allow_remote_shutdown',
                  'temp_dir',]
    exec_args = datastore_util.ArgsForGCDEmulator(start_args, args)
    exec_mock.assert_called_once_with(exec_args, log_file=None)

  def testWriteLegacyGCDEnvYaml(self):
    self._DoTestWriteGCDEnvYaml(True)

  def testWriteGCDEnvYaml(self):
    self._DoTestWriteGCDEnvYaml(False)

  def _DoTestWriteGCDEnvYaml(self, legacy):
    env_mock = self.StartObjectPatch(util, 'WriteEnvYaml')

    args = type(str('args_mock'),
                (object,),
                dict(host_port=arg_parsers.HostPort('localhost', '8080'),
                     store_on_disk=True,
                     data_dir='temp_dir',
                     legacy=legacy))
    datastore_util.WriteGCDEnvYaml(args)
    env = {'DATASTORE_HOST': 'http://localhost:8080',
           'DATASTORE_EMULATOR_HOST': 'localhost:8080',
           'DATASTORE_EMULATOR_HOST_PATH': 'localhost:8080/datastore',
           'DATASTORE_DATASET': self.Project(),
           'DATASTORE_PROJECT_ID': self.Project(),}
    env_mock.assert_called_once_with(env, 'temp_dir')

  def testWriteIPV6EnvYaml(self):
    env_mock = self.StartObjectPatch(util, 'WriteEnvYaml')

    args = type(str('args_mock'),
                (object,),
                dict(host_port=arg_parsers.HostPort('::', '8080'),
                     store_on_disk=True,
                     data_dir='temp_dir'))
    datastore_util.WriteGCDEnvYaml(args)
    env = {'DATASTORE_HOST': 'http://:::8080',
           'DATASTORE_EMULATOR_HOST': ':::8080',
           'DATASTORE_EMULATOR_HOST_PATH': ':::8080/datastore',
           'DATASTORE_DATASET': self.Project(),
           'DATASTORE_PROJECT_ID': self.Project(),}
    env_mock.assert_called_once_with(env, 'temp_dir')

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


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('myapp', '0008_auto_20150927_1351'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='like',
            name='count',
        ),
        migrations.RemoveField(
            model_name='like',
            name='ip_like',
        ),
        migrations.DeleteModel(
            name='Ip',
        ),
        migrations.RemoveField(
            model_name='news',
            name='like',
        ),
        migrations.RemoveField(
            model_name='plugin',
            name='ip_name',
        ),
        migrations.AddField(
            model_name='like',
            name='ip',
            field=models.IPAddressField(default=b'0.0.0.0'),
            preserve_default=True,
        ),
        migrations.AddField(
            model_name='like',
            name='url_news',
            field=models.URLField(default=b''),
            preserve_default=True,
        ),
        migrations.AddField(
            model_name='plugin',
            name='paginator_page',
            field=models.IntegerField(default=10),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='like',
            name='date_like',
            field=models.DateTimeField(),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='news',
            name='date_news',
            field=models.DateTimeField(),
            preserve_default=True,
        ),
        migrations.AlterField(
            model_name='news',
            name='title',
            field=models.CharField(max_length=40),
            preserve_default=True,
        ),
    ]


# This file analyzes the result of a voltage scan
# You can configure what it does using `volt_config.py`
# The input should be a csv file with the following columns:
#

import traceback

from volt_config import *
from consts import *

from numpy import *
import matplotlib as mpl
from matplotlib import pyplot as plt
from scipy.optimize import curve_fit
import sys, os
from typing import *

cmap_diverging = plt.get_cmap('RdBu')
cmap_normal    = plt.get_cmap('viridis')

coils_for_dim = {
    'x': (3, 4),
    'y': (5, 6),
    'z': (1, 2),
}
up_dn_sd_for_dim = {
    'x': (4, 7, 10),
    'y': (5, 9, 11),
    'z': (6, 8, 12),
}
sup_sdn_ssd_for_dim = {
    'x': (13, 16, 19),
    'y': (14, 18, 20),
    'z': (15, 17, 21),
}

def heatmap_for_property(data, v_min, v_max, coila, coilb, prop_name, diverging=False, is_abs=False, mg=False, is_fit=False):
    fig, ax = plt.subplots(figsize=(8, 6), dpi=192)

    if diverging:
        amax = max(abs(data.max()), abs(data.min()))
        norm = mpl.colors.Normalize(vmin=-amax, vmax=amax)
        mapp = mpl.cm.ScalarMappable(norm, cmap_diverging)
        cmap = cmap_diverging
    elif mg:  # milligauss, for error plot
        norm = mpl.colors.Normalize(vmin=0, vmax=data.max())
        mapp = mpl.cm.ScalarMappable(norm, cmap_normal)
        cmap = cmap_normal
    else:
        if is_abs:
            norm = mpl.colors.LogNorm(vmin=data.min(), vmax=data.max())
        else:
            norm = mpl.colors.Normalize(vmin=data.min(), vmax=data.max())
        mapp = mpl.cm.ScalarMappable(norm, cmap_normal)
        cmap = cmap_normal

    mapp.set_array([])

    extent = (0, upper_lim + 0.5, 0, upper_lim + 0.5 ) if is_fit else (v_min, v_max, v_min, v_max)

    ax.imshow(data.T, cmap=cmap, norm=norm, extent=extent, origin='lower')
    ax.set_xlabel(f"Voltage for Coil {coila} [V]")
    ax.set_ylabel(f"Voltage for Coil {coilb} [V]")
    ax.set_title(prop_name)
    fig.colorbar(mapp)
    return fig, ax

def bilinear(X, m1, m2, b):
    v0, v1 = X
    return (m1*v0) + (m2*v1) + b

def bilinear_fit(data: ndarray, dimension: str, coila: int, coilb: int):
    up, dn, sd = up_dn_sd_for_dim[dimension]
    # sup, sdn, ssd = sup_sdn_ssd_for_dim[dimension]

    v0 = data[:, :, 0].flatten()
    v1 = data[:, :, 1].flatten()

    b_up = data[:, :, up].flatten()
    # s_up = data[:, :, sup].flatten()

    b_dn = data[:, :, dn].flatten()
    # s_dn = data[:, :, sdn].flatten()

    b_sd = data[:, :, sd].flatten()
    # s_sd = data[:, :, ssd].flatten()

    p_up, c_up = curve_fit(bilinear, (v0, v1), b_up)  # , sigma=s_up)
    p_dn, c_dn = curve_fit(bilinear, (v0, v1), b_dn)  # , sigma=s_dn)
    p_sd, c_sd = curve_fit(bilinear, (v0, v1), b_sd)  # , sigma=s_sd)

    e_up = sqrt(diag(c_up))
    e_dn = sqrt(diag(c_dn))
    e_sd = sqrt(diag(c_sd))

    sys.stdout.write(f" {GREEN}Done.{RESET} Parameters:\n")
    for (d, p, e) in (('Up', p_up, e_up), ('Down', p_dn, e_dn), ('Side', p_sd, e_sd)):
        print("    %s% 4s%s:  (% 5.3f ± %5.3f) ⋅ V_%i  +  (% 5.3f ± %5.3f) ⋅ V_%i  +  (% 5.3f ± %5.3f)  =  B%s" % (
            BOLD, d, RESET, p[0], e[0], coila, p[1], e[1], coilb, p[2], e[2], dimension
        ))

    sys.stdout.write(f"  {BOLD}Down{RESET} full compensation:")
    sys.stdout.write(" V_%i  =  %5.3f  +  %5.3f ⋅ V_%i\n" % (coilb, (-p_dn[2]/p_dn[1]), (-p_dn[0]/p_dn[1]), coila))

    v0s = tile(linspace(0, upper_lim + 0.5, 1024), 1024)
    v1s = repeat(linspace(0, upper_lim + 0.5, 1024), 1024)

    bup = bilinear((v0s, v1s), *p_up)
    bdn = bilinear((v0s, v1s), *p_dn)
    bsd = bilinear((v0s, v1s), *p_sd)

    err = abs(bdn)

    imin = argmin(err)

    print(f"  Minimum of fit error at {GREEN}({v0s[imin]}V, {v1s[imin]}V): {MAGENTA}{err[imin]} mG{RESET}.")

    bup.resize(1024, 1024)
    bdn.resize(1024, 1024)
    bsd.resize(1024, 1024)

    return bup, bdn, bsd, (-p_dn[0]/p_dn[1]), (-p_dn[2]/p_dn[1])

if __name__ == "__main__":
    coila, coilb  = coils_for_dim[dimension]
    up, dn, sd    = up_dn_sd_for_dim[dimension]
    sup, sdn, ssd = sup_sdn_ssd_for_dim[dimension]

    print(f"Running analysis for {BOLD}{dimension.upper()}{RESET} (coils {coila} and {coilb}).")

    sys.stdout.write("Loading data...")

    try:
        rdata = loadtxt(scan_out, delimiter=',', skiprows=2, comments='#')
    except Exception:
        sys.stdout.write(f" {BR_RED}Couldn't read CSV.{RESET} Traceback:\n")
        traceback.print_exc()
        exit(1)

    dim = int(sqrt(rdata.shape[0]))
    data = zeros((dim, dim, 22))

    for i in range(dim):
        for j in range(dim):
            data[i, j, :] = rdata[dim * i + j, 2:]

    del rdata

    sys.stdout.write(f" {GREEN}Loaded data{RESET} ({dim} × {dim}).\n")

    # run fits

    sys.stdout.write(f"Running fits...")

    fit_up, fit_dn, fit_sd, fitm, fitb = bilinear_fit(data, dimension, coila, coilb)

    _heatmap = lambda dat, name, diverging=False, is_abs=False, mg=False, is_fit=False: \
        heatmap_for_property(
            dat, lower_lim - resolution / 2, upper_lim + resolution / 2, coila, coilb, name, diverging, is_abs, mg, is_fit
        )

    bstr = 'B_' + dimension

    PLOTS: List[Tuple[str, Callable]] = [
        ('top_b',    lambda data: _heatmap(data[:,:,up],  f'Top ${bstr}$ [G]', True)),
        ('bottom_b', lambda data: _heatmap(data[:,:,dn],  f'Bottom ${bstr}$ [G]', True)),
        ('side_b',   lambda data: _heatmap(data[:,:,sd],  f'Side ${bstr}$ [G]', True)),
        ('s_top_b',  lambda data: _heatmap(data[:,:,sup], f'σ Top ${bstr}$ [G]', True)),
        ('err_sum',  lambda data:
          _heatmap(abs(data[:,:,dn])+abs(data[:,:,sd])+1e-9, f'|Bottom ${bstr}$| + 0.2|Side ${bstr}$|', False, True)
        ),
        ('top_fit',    lambda data: _heatmap(fit_up.T, f'Fit Top ${bstr}$ [G]', True, is_fit=True)),
        ('bottom_fit', lambda data: _heatmap(fit_dn.T, f'Fit Bottom ${bstr}$ [G]', True, is_fit=True)),
        ('side_fit',   lambda data: _heatmap(fit_sd.T, f'Fit Side ${bstr}$ [G]', True, is_fit=True)),
    ]

    err = (abs(data[:,:,dn])).flatten()
    i_min_err = argmin(err)
    # print(data[:,:,0].shape, "    ", i_min_err)
    min_v0    = data[:,:,0].flatten()[i_min_err]
    min_v1    = data[:,:,1].flatten()[i_min_err]
    print(f"Minimum of measured error at {GREEN} ({min_v0}V, {min_v1}V): {MAGENTA}{1000*err[i_min_err]} mG{RESET}.")

    n_plots = len(PLOTS)

    if do_plots:
        for i, (name, closure) in enumerate(PLOTS):
            sys.stdout.write(f"\r{CLEAR_LINE}Running plot {i+1}/{n_plots}: '{name}'")
            fig, ax = closure(data)
            if name == 'bottom_fit':
                ax.plot(
                    [0, upper_lim + 0.5],
                    [fitb, fitm * (upper_lim + 0.5) + fitb],
                    c='black',
                    ls='--',
                    label='Fit'
                )
                ax.set_xlim(0, upper_lim + 0.5)
                ax.set_ylim(0, upper_lim + 0.5)
            # fig.savefig(os.path.join(plot_dir, f'{name}_{dimension}_{run_addl}.pgf'))
            fig.savefig(os.path.join(plot_dir, f'{name}_{dimension}_{run_addl}.png'))

        sys.stdout.write(f"\r{CLEAR_LINE}Plots {GREEN}done{RESET}.")


from rest_framework import viewsets, permissions, status
from rest_framework.response import Response
from rest_framework.decorators import action
from django.db import transaction

from .models import Item, UserItem, Categories
from .serializers import ItemSerializer, UserItemSerializer, CateSerializer

class CateViewSet(viewsets.ModelViewSet):
    queryset = Categories.objects.all()
    serializer_class = CateSerializer

    @action(detail=True)
    def items(self, request, *args, **kwargs):
        cate = self.get_object()
        serializer = ItemSerializer(cate.items.all(), many=True)
        return Response(serializer.data)

class ItemViewSet(viewsets.ModelViewSet):
    queryset = Item.objects.all()
    serializer_class = ItemSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    @action(detail=True, methods=['POST'])
    def purchase(self, request, *args, **kwargs):
        item = self.get_object()
        user = request.user
        if item.price > user.point:
            return Response(status=status.HTTP_402_PAYMENT_REQUIRED)
        user.point -= item.price
        user.save()
        try:
            user_item = UserItem.objects.get(user=user, item=item)
        except UserItem.DoesNotExist:
            user_item = UserItem(user=user, item=item)
        user_item.count += 1
        user_item.save()

        serializer = UserItemSerializer(user.items.all(), many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['POST'], url_path='purchase')
    @transaction.atomic()
    def purchase_items(selfs, request, *args, **kwargs):
        items = request.data['items']
        user = request.user

        sid = transaction.savepoint()
        for i in items:
            item = Item.objects.get(id=i['item_id'])
            count = int(i['count'])

            if item.price * count > user.point:
                transaction.savepoint_rollback(sid)
                return Response(status=status.HTTP_402_PAYMENT_REQUIRED)
            user.point -= item.price
            user.save()
            try:
                user_item = UserItem.objects.get(user=user, item=item)
            except UserItem.DoesNotExist:
                user_item = UserItem(user=user, item=item)
            user_item.count += count
            user_item.save()
        transaction.savepoint_commit(sid)
        serializer = UserItemSerializer(user.items.all(), many=True)
        return Response(serializer.data)