# Copyright (c) 2012 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.

"""Base class for Android Python-driven tests.

This test case is intended to serve as the base class for any Python-driven
tests. It is similar to the Python unitttest module in that the user's tests
inherit from this case and add their tests in that case.

When a PythonTestBase object is instantiated, its purpose is to run only one of
its tests. The test runner gives it the name of the test the instance will
run. The test runner calls SetUp with the Android device ID which the test will
run against. The runner runs the test method itself, collecting the result,
and calls TearDown.

Tests can basically do whatever they want in the test methods, such as call
Java tests using _RunJavaTests. Those methods have the advantage of massaging
the Java test results into Python test results.
"""

import logging
import os
import time

import android_commands
import apk_info
from run_java_tests import TestRunner
from test_result import SingleTestResult, TestResults


# aka the parent of com.google.android
BASE_ROOT = 'src' + os.sep


class PythonTestBase(object):
  """Base class for Python-driven tests."""

  def __init__(self, test_name):
    # test_name must match one of the test methods defined on a subclass which
    # inherits from this class.
    # It's stored so we can do the attr lookup on demand, allowing this class
    # to be pickled, a requirement for the multiprocessing module.
    self.test_name = test_name
    class_name = self.__class__.__name__
    self.qualified_name = class_name + '.' + self.test_name

  def SetUp(self, options):
    self.options = options
    self.shard_index = self.options.shard_index
    self.device_id = self.options.device_id
    self.adb = android_commands.AndroidCommands(self.device_id)
    self.ports_to_forward = []

  def TearDown(self):
    pass

  def GetOutDir(self):
    return os.path.join(os.environ['CHROME_SRC'], 'out',
        self.options.build_type)

  def Run(self):
    logging.warning('Running Python-driven test: %s', self.test_name)
    return getattr(self, self.test_name)()

  def _RunJavaTest(self, fname, suite, test):
    """Runs a single Java test with a Java TestRunner.

    Args:
      fname: filename for the test (e.g. foo/bar/baz/tests/FooTest.py)
      suite: name of the Java test suite (e.g. FooTest)
      test: name of the test method to run (e.g. testFooBar)

    Returns:
      TestResults object with a single test result.
    """
    test = self._ComposeFullTestName(fname, suite, test)
    apks = [apk_info.ApkInfo(self.options.test_apk_path,
            self.options.test_apk_jar_path)]
    java_test_runner = TestRunner(self.options, self.device_id, [test], False,
                                  self.shard_index,
                                  apks,
                                  self.ports_to_forward)
    return java_test_runner.Run()

  def _RunJavaTests(self, fname, tests):
    """Calls a list of tests and stops at the first test failure.

    This method iterates until either it encounters a non-passing test or it
    exhausts the list of tests. Then it returns the appropriate Python result.

    Args:
      fname: filename for the Python test
      tests: a list of Java test names which will be run

    Returns:
      A TestResults object containing a result for this Python test.
    """
    start_ms = int(time.time()) * 1000

    result = None
    for test in tests:
      # We're only running one test at a time, so this TestResults object will
      # hold only one result.
      suite, test_name = test.split('.')
      result = self._RunJavaTest(fname, suite, test_name)
      # A non-empty list means the test did not pass.
      if result.GetAllBroken():
        break

    duration_ms = int(time.time()) * 1000 - start_ms

    # Do something with result.
    return self._ProcessResults(result, start_ms, duration_ms)

  def _ProcessResults(self, result, start_ms, duration_ms):
    """Translates a Java test result into a Python result for this test.

    The TestRunner class that we use under the covers will return a test result
    for that specific Java test. However, to make reporting clearer, we have
    this method to abstract that detail and instead report that as a failure of
    this particular test case while still including the Java stack trace.

    Args:
      result: TestResults with a single Java test result
      start_ms: the time the test started
      duration_ms: the length of the test

    Returns:
      A TestResults object containing a result for this Python test.
    """
    test_results = TestResults()

    # If our test is in broken, then it crashed/failed.
    broken = result.GetAllBroken()
    if broken:
      # Since we have run only one test, take the first and only item.
      single_result = broken[0]

      log = single_result.log
      if not log:
        log = 'No logging information.'

      python_result = SingleTestResult(self.qualified_name, start_ms,
                                       duration_ms,
                                       log)

      # Figure out where the test belonged. There's probably a cleaner way of
      # doing this.
      if single_result in result.crashed:
        test_results.crashed = [python_result]
      elif single_result in result.failed:
        test_results.failed = [python_result]
      elif single_result in result.unknown:
        test_results.unknown = [python_result]

    else:
      python_result = SingleTestResult(self.qualified_name, start_ms,
                                       duration_ms)
      test_results.ok = [python_result]

    return test_results

  def _ComposeFullTestName(self, fname, suite, test):
    package_name = self._GetPackageName(fname)
    return package_name + '.' + suite + '#' + test

  def _GetPackageName(self, fname):
    """Extracts the package name from the test file path."""
    dirname = os.path.dirname(fname)
    package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):]
    return package.replace(os.sep, '.')
