# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import mock
import unittest

import common
from autotest_lib.frontend import setup_django_lite_environment
from autotest_lib.frontend.afe import frontend_test_utils
from autotest_lib.scheduler import rdb
from autotest_lib.scheduler import rdb_hosts
from autotest_lib.scheduler import rdb_requests
from autotest_lib.scheduler import rdb_testing_utils
from autotest_lib.scheduler import rdb_utils


from django.core import exceptions as django_exceptions
from django.db.models import fields


class RDBBaseRequestHandlerTests(unittest.TestCase):
    """Base Request Handler Unittests."""

    def setUp(self):
        self.handler = rdb.BaseHostRequestHandler()
        self.handler.host_query_manager = mock.MagicMock()
        self.update_manager = rdb_requests.BaseHostRequestManager(
                rdb_requests.UpdateHostRequest, rdb.update_hosts)
        self.get_hosts_manager = rdb_requests.BaseHostRequestManager(
                rdb_requests.HostRequest, rdb.get_hosts)


    def tearDown(self):
        self.handler.host_query_manager.reset_mock()


    def testResponseMapUpdate(self):
        """Test response map behaviour.

        Test that either adding an empty response against a request, or 2
        responses for the same request will raise an exception.
        """
        self.get_hosts_manager.add_request(host_id=1)
        request = self.get_hosts_manager.request_queue[0]
        response = []
        self.assertRaises(
                rdb_utils.RDBException, self.handler.update_response_map,
                *(request, response))
        response.append(rdb_testing_utils.FakeHost(hostname='host', host_id=1))
        self.handler.update_response_map(request, response)
        self.assertRaises(
                rdb_utils.RDBException, self.handler.update_response_map,
                *(request, response))


    def testResponseMapChecking(self):
        """Test response map sanity check.

        Test that adding the same RDBHostServerWrapper for 2 requests will
        raise an exception.
        """
        # Assign the same host to 2 requests and check for exceptions.
        self.get_hosts_manager.add_request(host_id=1)
        self.get_hosts_manager.add_request(host_id=2)
        request_1 = self.get_hosts_manager.request_queue[0]
        request_2 = self.get_hosts_manager.request_queue[1]
        response = [rdb_testing_utils.FakeHost(hostname='host', host_id=1)]

        self.handler.update_response_map(request_1, response)
        self.handler.update_response_map(request_2, response)
        self.assertRaises(
                rdb_utils.RDBException, self.handler.get_response)

        # Assign the same exception to 2 requests and make sure there isn't a
        # an exception, then check that the response returned is the
        # exception_string and not the exception itself.
        self.handler.response_map = {}
        exception_string = 'This is an exception'
        response = [rdb_utils.RDBException(exception_string)]
        self.handler.update_response_map(request_1, response)
        self.handler.update_response_map(request_2, response)
        for response in self.handler.get_response().values():
            self.assertTrue(response[0] == exception_string)


    def testBatchGetHosts(self):
        """Test getting hosts.

        Verify that:
            1. We actually call get_hosts on the query_manager for a
                batched_get_hosts request.
            2. The hosts returned are matched up correctly with requests,
                and each request gets exactly one response.
            3. The hosts returned have all the fields needed to create an
                RDBClientHostWrapper, in spite of having gone through the
                to_wire process of serialization in get_response.
        """
        fake_hosts = []
        for host_id in range(1, 4):
            self.get_hosts_manager.add_request(host_id=host_id)
            fake_hosts.append(
                    rdb_testing_utils.FakeHost('host%s'%host_id, host_id))
        self.handler.host_query_manager.get_hosts = mock.MagicMock(
                return_value=fake_hosts)
        self.handler.batch_get_hosts(self.get_hosts_manager.request_queue)
        for request, hosts in self.handler.get_response().iteritems():
            self.assertTrue(len(hosts) == 1)
            client_host = rdb_hosts.RDBClientHostWrapper(**hosts[0])
            self.assertTrue(request.host_id == client_host.id)


    def testSingleUpdateRequest(self):
        """Test that a single host update request hits the query manager."""
        payload = {'status': 'Ready'}
        host_id = 10
        self.update_manager.add_request(host_id=host_id, payload=payload)
        self.handler.update_hosts(self.update_manager.request_queue)
        self.handler.host_query_manager.update_hosts.assert_called_once_with(
                [host_id], **payload)


    def testDedupingSameHostRequests(self):
        """Test same host 2 updates deduping."""
        payload_1 = {'status': 'Ready'}
        payload_2 = {'locked': True}
        host_id = 10
        self.update_manager.add_request(host_id=host_id, payload=payload_1)
        self.update_manager.add_request(host_id=host_id, payload=payload_2)
        self.handler.update_hosts(self.update_manager.request_queue)
        self.handler.host_query_manager.update_hosts.assert_called_once_with(
                [host_id], **dict(payload_1.items() + payload_2.items()))


    def testLastUpdateWins(self):
        """Test 2 updates to the same row x column."""
        payload_1 = {'status': 'foobar'}
        payload_2 = {'status': 'Ready'}
        host_id = 10
        self.update_manager.add_request(host_id=host_id, payload=payload_1)
        self.update_manager.add_request(host_id=host_id, payload=payload_2)
        self.handler.update_hosts(self.update_manager.request_queue)
        self.handler.host_query_manager.update_hosts.assert_called_once_with(
                [host_id], **payload_2)


    def testDedupingSamePayloadRequests(self):
        """Test same payload for 2 hosts only hits the db once."""
        payload = {'status': 'Ready'}
        host_1_id = 10
        host_2_id = 20
        self.update_manager.add_request(host_id=host_1_id, payload=payload)
        self.update_manager.add_request(host_id=host_2_id, payload=payload)
        self.handler.update_hosts(self.update_manager.request_queue)
        self.handler.host_query_manager.update_hosts.assert_called_once_with(
                [host_1_id, host_2_id], **payload)


    def testUpdateException(self):
        """Test update exception handling.

        1. An exception raised while processing one update shouldn't prevent
            the others.
        2. The exception shold get serialized as a string and returned via the
            response map.
        """
        payload = {'status': 'Ready'}
        exception_msg = 'Bad Field'
        exception_types = [django_exceptions.FieldError,
                           fields.FieldDoesNotExist]
        self.update_manager.add_request(host_id=11, payload=payload)
        self.update_manager.add_request(host_id=10, payload=payload)
        mock_query_manager = self.handler.host_query_manager

        for e, request in zip(
                exception_types, self.update_manager.request_queue):
            mock_query_manager.update_hosts.side_effect = e(exception_msg)
            self.handler.update_hosts([request])

        response = self.handler.get_response()
        for request in self.update_manager.request_queue:
            self.assertTrue(exception_msg in response.get(request))


class QueryManagerTests(unittest.TestCase,
                        frontend_test_utils.FrontendTestMixin):
    """Query Manager Tests."""

    def setUp(self):
        self.db_helper = rdb_testing_utils.DBHelper()
        self._database = self.db_helper.database

        # Runs syncdb setting up initial database conditions
        self._frontend_common_setup()
        self.available_hosts_query_manager = rdb.AvailableHostQueryManager()
        self.all_hosts_query_manager = rdb.BaseHostQueryManager()


    def tearDown(self):
        self._database.disconnect()
        self._frontend_common_teardown()


    def testFindHosts(self):
        """Test finding hosts.

        Tests that we can only find unleased hosts through the
        available_hosts_query_manager.
        """
        deps = set(['a', 'b'])
        acls = set(['a'])
        db_host = self.db_helper.create_host(
                name='h1', deps=deps, acls=acls, leased=1)
        hosts = self.all_hosts_query_manager.find_hosts(
                deps=[lable.id for lable in db_host.labels.all()],
                acls=[aclgroup.id for aclgroup in db_host.aclgroup_set.all()])
        self.assertTrue(type(hosts) == list and len(hosts) == 1)
        hosts = self.available_hosts_query_manager.find_hosts(
                deps=[lable.id for lable in db_host.labels.all()],
                acls=[aclgroup.id for aclgroup in db_host.aclgroup_set.all()])
        # We should get an empty list if there are no matching hosts, not a
        # QuerySet or None.
        self.assertTrue(len(hosts) == 0)


    def testUpdateHosts(self):
        """Test updating hosts.

        Test that we can only update unleased hosts through the
        available_hosts_query_manager.
        """
        deps = set(['a', 'b'])
        acls = set(['a'])
        db_host = self.db_helper.create_host(
                name='h1', deps=deps, acls=acls, leased=1)
        # Confirm that the available_hosts_manager can't see the leased host.
        self.assertTrue(
                len(self.available_hosts_query_manager.get_hosts(
                        [db_host.id])) == 0)

        # Confirm that the available_hosts_manager can't update a leased host.
        # Also confirm that the general query manager Can see the leased host.
        self.available_hosts_query_manager.update_hosts(
                [db_host.id], **{'leased': 0})
        hosts = self.all_hosts_query_manager.get_hosts([db_host.id])
        self.assertTrue(len(hosts) == 1 and hosts[0].leased)

        # Confirm that we can infact update the leased bit on the host.
        self.all_hosts_query_manager.update_hosts(
                [hosts[0].id], **{'leased': 0})
        hosts = self.all_hosts_query_manager.get_hosts([hosts[0].id])
        self.assertTrue(len(hosts) == 1 and not hosts[0].leased)



