# Copyright 2013 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.

"""Runs linker tests on a particular device."""

import logging
import os.path
import sys
import traceback

from pylib import constants
from pylib.base import base_test_result
from pylib.base import base_test_runner
from pylib.linker import test_case
from pylib.utils import apk_helper


# Name of the Android package to install for this to work.
_PACKAGE_NAME = 'ChromiumLinkerTest'


class LinkerExceptionTestResult(base_test_result.BaseTestResult):
  """Test result corresponding to a python exception in a host-custom test."""

  def __init__(self, test_name, exc_info):
    """Constructs a LinkerExceptionTestResult object.

    Args:
      test_name: name of the test which raised an exception.
      exc_info: exception info, ostensibly from sys.exc_info().
    """
    exc_type, exc_value, exc_traceback = exc_info
    trace_info = ''.join(traceback.format_exception(exc_type, exc_value,
                                                    exc_traceback))
    log_msg = 'Exception:\n' + trace_info

    super(LinkerExceptionTestResult, self).__init__(
        test_name,
        base_test_result.ResultType.FAIL,
        log="%s %s" % (exc_type, log_msg))


class LinkerTestRunner(base_test_runner.BaseTestRunner):
  """Orchestrates running a set of linker tests.

  Any Python exceptions in the tests are caught and translated into a failed
  result, rather than being re-raised on the main thread.
  """

  #override
  def __init__(self, device, tool, cleanup_test_files):
    """Creates a new LinkerTestRunner.

    Args:
      device: Attached android device.
      tool: Name of the Valgrind tool.
      cleanup_test_files: Whether or not to cleanup test files on device.
    """

    super(LinkerTestRunner, self).__init__(device, tool, cleanup_test_files)

  #override
  def InstallTestPackage(self):
    apk_path = os.path.join(
        constants.GetOutDirectory(), 'apks', '%s.apk' % _PACKAGE_NAME)

    if not os.path.exists(apk_path):
      raise Exception('%s not found, please build it' % apk_path)

    package_name = apk_helper.GetPackageName(apk_path)
    self.device.old_interface.ManagedInstall(apk_path, package_name)

  #override
  def RunTest(self, test):
    """Sets up and runs a test case.

    Args:
      test: An object which is ostensibly a subclass of LinkerTestCaseBase.

    Returns:
      A TestRunResults object which contains the result produced by the test
      and, in the case of a failure, the test that should be retried.
    """

    assert isinstance(test, test_case.LinkerTestCaseBase)

    try:
      results = test.Run(self.device)
    except Exception:
      logging.exception('Caught exception while trying to run test: ' +
                        test.tagged_name)
      exc_info = sys.exc_info()
      results = base_test_result.TestRunResults()
      results.AddResult(LinkerExceptionTestResult(
          test.tagged_name, exc_info))

    if not results.DidRunPass():
      return results, test
    else:
      return results, None
