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

"""Adds unittest-esque functionality to Legion."""

import argparse
import logging
import sys
import unittest

#pylint: disable=relative-import
import common_lib
import task_controller
import task_registration_server

BANNER_WIDTH = 80


class TestCase(unittest.TestCase):
  """Test case class with added Legion support."""

  _registration_server = None
  _initialized = False

  @classmethod
  def __new__(cls, *args, **kwargs):
    """Initialize the class and return a new instance."""
    cls._InitializeClass()
    return super(TestCase, cls).__new__(*args, **kwargs)

  def __init__(self, test_name='runTest'):
    super(TestCase, self).__init__(test_name)
    method = getattr(self, test_name, None)
    if method:
      # Install the _RunTest method
      self._TestMethod = method
      setattr(self, test_name, self._RunTest)
    self._output_dir = None

  @property
  def output_dir(self):
    if not self._output_dir:
      self._output_dir = self.rpc.GetOutputDir()
    return self._output_dir

  def _RunTest(self):
    """Runs the test method and provides banner info and error reporting."""
    self._LogInfoBanner(self._testMethodName, self.shortDescription())
    try:
      return self._TestMethod()
    except:
      exc_info = sys.exc_info()
      logging.error('', exc_info=exc_info)
      raise exc_info[0], exc_info[1], exc_info[2]

  @classmethod
  def _InitializeClass(cls):
    """Handles class level initialization.

    There are 2 types of setup/teardown methods that always need to be run:
    1) Framework level setup/teardown
    2) Test case level setup/teardown

    This method installs handlers in place of setUpClass and tearDownClass that
    will ensure both types of setup/teardown methods are called correctly.
    """
    if cls._initialized:
      return
    cls._OriginalSetUpClassMethod = cls.setUpClass
    cls.setUpClass = cls._HandleSetUpClass
    cls._OriginalTearDownClassMethod = cls.tearDownClass
    cls.tearDownClass = cls._HandleTearDownClass
    cls._initialized = True

  @classmethod
  def _LogInfoBanner(cls, method_name, method_doc=None):
    """Formats and logs test case information."""
    logging.info('*' * BANNER_WIDTH)
    logging.info(method_name.center(BANNER_WIDTH))
    if method_doc:
      for line in method_doc.split('\n'):
        logging.info(line.center(BANNER_WIDTH))
    logging.info('*' * BANNER_WIDTH)

  @classmethod
  def CreateTask(cls, *args, **kwargs):
    """Convenience method to create a new task."""
    task = task_controller.TaskController(*args, **kwargs)
    cls._registration_server.RegisterTaskCallback(
        task.otp, task.OnConnect)
    return task

  @classmethod
  def _SetUpFramework(cls):
    """Perform the framework-specific setup operations."""
    cls._registration_server = (
        task_registration_server.TaskRegistrationServer())
    cls._registration_server.Start()

  @classmethod
  def _TearDownFramework(cls):
    """Perform the framework-specific teardown operations."""
    if cls._registration_server:
      cls._registration_server.Shutdown()
    task_controller.TaskController.ReleaseAllTasks()

  @classmethod
  def _HandleSetUpClass(cls):
    """Performs common class-level setup operations.

    This method performs test-wide setup such as starting the registration
    server and then calls the original setUpClass method."""
    try:
      common_lib.InitLogging()
      cls._LogInfoBanner('setUpClass', 'Performs class level setup.')
      cls._SetUpFramework()
      cls._OriginalSetUpClassMethod()
    except:
      # Make sure we tear down in case of any exceptions
      cls._HandleTearDownClass(setup_failed=True)
      exc_info = sys.exc_info()
      logging.error('', exc_info=exc_info)
      raise exc_info[0], exc_info[1], exc_info[2]

  @classmethod
  def _HandleTearDownClass(cls, setup_failed=False):
    """Performs common class-level tear down operations.

    This method calls the original tearDownClass then performs test-wide
    tear down such as stopping the registration server.
    """
    cls._LogInfoBanner('tearDownClass', 'Performs class level tear down.')
    try:
      if not setup_failed:
        cls._OriginalTearDownClassMethod()
    finally:
      cls._TearDownFramework()


def main():
  unittest.main(verbosity=0, argv=sys.argv[:1])
