# Copyright 2019 Google LLC
#
# 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 host_event_api module."""

import datetime

import mock


from tradefed_cluster import api_test
from tradefed_cluster import datastore_entities
from tradefed_cluster import device_manager
from tradefed_cluster import host_event
from tradefed_cluster import host_event_api
from tradefed_cluster.services import task_scheduler
import unittest

device_info_emulator = {
    'product': 'unknown',
    'state': 'Available',
    'device_serial': 'emulator-5554',
    'sdk_version': 'unknown',
    'build_id': 'unknown',
    'run_target': 'unknown',
    'product_variant': 'unknown'
}
device_info_hammerhead = {
    'product': 'hammerhead',
    'state': 'Available',
    'device_serial': '021f34c1d01e5a59',
    'sdk_version': '23',
    'build_id': 'MASTER',
    'run_target': 'hammerhead',
    'product_variant': 'hammerhead'
}
snapshot_event = {
    'time': 1234567890,
    'data': {},
    'cluster': 'example-cluster',
    'hostname': 'example0.mtv.corp.example.com',
    'lab_name': 'alab',
    'event_type': 'DEVICE_SNAPSHOT',
    'device_infos': [device_info_emulator, device_info_hammerhead]
}
host_state_event = {
    'time': 1234567890,
    'cluster': 'example-cluster',
    'hostname': 'example0.mtv.corp.example.com',
    'event_type': 'HOST_STATE_CHANGED',
    'host_state': 'KILLING',
}


class MockDefer(object):
  """Mock methods to replace host_event_api deferred methods.

  We cannot use the mock library to do this as deferred will error out with an
  error related to module name changes (some black magic that the mock library
  uses when replacing method implementations).
  """

  deferred_ran = None
  events = None

  @classmethod
  def ProcessHostEventA(cls, events):
    assert events is not None
    cls.deferred_ran = 'A'
    cls.events = events

  @classmethod
  def ProcessHostEventB(cls, events):
    assert events is not None
    cls.deferred_ran = 'B'
    cls.events = events


class HostEventApiTest(api_test.ApiTest):

  def testSubmitHostEvents(self):
    request = {'host_events': [snapshot_event]}
    # Verify that there aren't any entities persisted before the API call
    hosts = datastore_entities.HostInfo.query().fetch()
    self.assertEqual(0, len(hosts))
    devices = datastore_entities.DeviceInfo.query().fetch()
    self.assertEqual(0, len(devices))
    self.testapp.post_json('/_ah/api/HostEventApi.SubmitHostEvents', request)

    tasks = self.mock_task_scheduler.GetTasks(
        queue_names=host_event.HOST_EVENT_QUEUE_NDB)
    self.assertEqual(len(tasks), 1)
    task_scheduler.RunCallableTask(tasks[0].payload)
    # Verify host info in datastore.
    hosts = datastore_entities.HostInfo.query().fetch()
    timestamp = datetime.datetime.utcfromtimestamp(int(snapshot_event['time']))
    self.assertEqual(1, len(hosts))
    self.assertEqual(snapshot_event['hostname'], hosts[0].hostname)
    self.assertEqual(snapshot_event['lab_name'], hosts[0].lab_name)
    self.assertEqual(snapshot_event['cluster'], hosts[0].physical_cluster)
    self.assertEqual(timestamp, hosts[0].timestamp)
    devices = datastore_entities.DeviceInfo.query().fetch()
    self.assertEqual(2, len(devices))

  def testSubmitHostEvents_hostStateChangedEvent(self):
    request = {'host_events': [host_state_event]}
    self.testapp.post_json('/_ah/api/HostEventApi.SubmitHostEvents', request)
    tasks = self.mock_task_scheduler.GetTasks(
        queue_names=host_event.HOST_EVENT_QUEUE_NDB)
    self.assertEqual(len(tasks), 1)
    host_event_api.HostEventApi._ProcessHostEventWithNDB = (
        MockDefer.ProcessHostEventA)
    task_scheduler.RunCallableTask(tasks[0].payload)
    event = host_event.HostEvent(**MockDefer.events[0])
    self.assertEqual('HOST_STATE_CHANGED', event.type)
    self.assertEqual('KILLING', event.host_state)

  def testSubmitHostEvents_changeDeferredFunction(self):
    """Tests that tasks execute the latest deferred function implementation."""
    MockDefer.deferred_ran = None
    request = {'host_events': [snapshot_event]}
    # Sending 3 requests and run each with a different version
    self.testapp.post_json('/_ah/api/HostEventApi.SubmitHostEvents', request)
    self.testapp.post_json('/_ah/api/HostEventApi.SubmitHostEvents', request)
    self.testapp.post_json('/_ah/api/HostEventApi.SubmitHostEvents', request)
    tasks = self.mock_task_scheduler.GetTasks(
        queue_names=host_event.HOST_EVENT_QUEUE_NDB)
    self.assertEqual(len(tasks), 3)
    task_scheduler.RunCallableTask(tasks[0].payload)
    self.assertIsNone(MockDefer.deferred_ran)
    host_event_api.HostEventApi._ProcessHostEventWithNDB = (
        MockDefer.ProcessHostEventA)
    task_scheduler.RunCallableTask(tasks[1].payload)
    self.assertEqual('A', MockDefer.deferred_ran)
    host_event_api.HostEventApi._ProcessHostEventWithNDB = (
        MockDefer.ProcessHostEventB)
    task_scheduler.RunCallableTask(tasks[2].payload)
    self.assertEqual('B', MockDefer.deferred_ran)

  @mock.patch.object(task_scheduler, 'AddCallableTask')
  def testSubmitHostEvents_multipleChunks(self, mock_defer):
    """Tests a request with more vents than the chunk size."""
    host_event_api.CHUNK_SIZE = 5
    request = {'host_events': [snapshot_event] * 50}
    self.testapp.post_json('/_ah/api/HostEventApi.SubmitHostEvents', request)
    # Should be called 10 times with 5 chunks each
    mock_defer.assert_has_calls([
        mock.call(mock.ANY, [snapshot_event] * 5,
                  _queue=host_event.HOST_EVENT_QUEUE_NDB,
                  _target='testbed-version.default')] * 10)

  def testSubmitHostEvents_emptyRequest(self):
    request = {}
    res = self.testapp.post_json(
        '/_ah/api/HostEventApi.SubmitHostEvents', request,
        expect_errors=True)
    self.assertEqual('400 Bad Request', res.status)

  @mock.patch.object(device_manager, 'HandleDeviceSnapshotWithNDB')
  @mock.patch.object(device_manager, 'IsHostEventValid', return_value=False)
  def testProcessHostEvent_invalidEvent(self, mock_valid, mock_handle):
    """Tests _ProcessHostEvent with an invalid event."""
    host_event_api.HostEventApi()._ProcessHostEventWithNDB([snapshot_event])
    mock_valid.assert_called_once_with(snapshot_event)
    self.assertFalse(mock_handle.called)

  def testChunks(self):
    """Test host_event_api.chunks()."""
    l = [1, 2, 3, 4, 5]
    result = [c for c in host_event_api.chunks(l, 2)]
    self.assertEqual(3, len(result))
    self.assertEqual([1, 2], result[0])
    self.assertEqual([3, 4], result[1])
    self.assertEqual([5], result[2])

  def testChunks_emptyList(self):
    """Test host_event_api.chunks() given an empty list."""
    result = [c for c in host_event_api.chunks([], 2)]
    self.assertEqual(0, len(result))


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