# -*- coding: utf-8 -*-
# Copyright 2010-2014, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""A script to run unittests on android.

This file searches all tests under --test_bin_dir (the default is the current
directory), and run them on android (emulator or actual device).
You need to run an android emulator or to connect a dvice, before running this
script.
"""

__author__ = "hidehiko"

import errno
import logging
import multiprocessing
import optparse
import os
import subprocess
import time
from xml.etree import cElementTree as ElementTree
from build_tools import android_util
from build_tools.test_tools import gtest_report


def FindTestBinaries(test_dir):
  """Returns the file names of tests."""
  logging.info('Gathering binaries in %s.', os.path.abspath(test_dir))
  result = []

  for f in os.listdir(test_dir):
    path = os.path.join(test_dir, f)
    # Test binaries are "executable file" and "its name ends with _test."
    if (os.access(path, os.R_OK | os.X_OK) and
        os.path.isfile(path) and
        f.endswith('_test')):
      result.append(f)
  return result


def ParseArgs():
  """Parses command line options and returns them."""
  parser = optparse.OptionParser()
  parser.add_option('--run_java_test', dest='run_java_test', default=False,
                    action='store_true',
                    help='Runs JUnit tests. [JAVA] options are used.')
  android_devices_default = os.environ.get('ANDROID_DEVICES', '')
  parser.add_option('--android_devices', dest='android_devices',
                    default=android_devices_default,
                    help='[JAVA][NATIVE] Comma separated serial numbers '
                    'on which devices the tests run. '
                    'If not specified all the available devices are used.')
  parser.add_option('--run_native_test', dest='run_native_test', default=False,
                    action='store_true',
                    help='Runs native tests. [NATIVE] options are used.')
  parser.add_option('--configuration', dest='configuration',
                    default='Debug',
                    help='[JAVA] Build configuration. Used to build correct '
                    'testee binary.')
  parser.add_option('--app_package_name', dest='app_package_name',
                    default='org.mozc.android.inputmethod.japanese',
                    help='[JAVA] Testee project\'s package name. '
                    'This is used to find test reporting XML file.')
  parser.add_option('--remote_dir', dest='remote_dir',
                    default='/sdcard/mozctest',
                    help='[NATIVE] Working directory on '
                    'a SD card on a Android device')
  parser.add_option('--remote_device', dest='remote_device',
                    default='/dev/block/vold/179:0',
                    help='[NATIVE] Path to the device to be (re)mounted.')
  parser.add_option('--remote_mount_point', dest='remote_mount_point',
                    default='/sdcard',
                    help='[NATIVE] Mount point for the --remote_device.')
  parser.add_option('--test_bin_dir', dest='test_bin_dir', default='.',
                    help='[NATIVE] The directory which contains test binaries')
  parser.add_option('--test_case', dest='testcase', default='',
                    help='[NATIVE] Limits testcases to run.')
  parser.add_option('--native_abi', dest='abi', default='armeabi',
                    help='[JAVA][NATIVE] ABI of built test executables.')
  parser.add_option('--mozc_dictionary_data_file',
                    dest='mozc_dictionary_data_file', default=None,
                    help='[NATIVE] Path to system.dictionary file.')
  parser.add_option('--mozc_connection_data_file',
                    dest='mozc_connection_data_file', default=None,
                    help='[NATIVE] Path to connection.data file.')
  parser.add_option('--mozc_connection_text_data_file',
                    dest='mozc_connection_text_data_file', default=None,
                    help='[NATIVE] Path to connection_single_column.txt file.')
  parser.add_option('--mozc_test_connection_data_file',
                    dest='mozc_test_connection_data_file', default=None,
                    help='[NATIVE] Path to test_connection.data file.')
  parser.add_option('--mozc_test_connection_text_data_file',
                    dest='mozc_test_connection_text_data_file', default=None,
                    help='[NATIVE] Path to connection_single_column.txt file.')
  parser.add_option('--mozc_data_dir',
                    dest='mozc_data_dir', default=None,
                    help='[NATIVE] Path to data directory.')
  parser.add_option('--output_report_dir', dest='output_report_dir',
                    default=None,
                    help='[JAVA][NATIVE] Path to output gtest '
                    'reporting XML files')
  parser.add_option('--android_home', dest='android_home',
                    default=None,
                    help='[JAVA][NATIVE] Path to the the SDK.')
  return parser.parse_args()[0]


def AppendPrefixToSuiteName(in_file_name, out_file_name, prefix):
  """Appends prefix to <testsuite> element's name attribute."""

  def AppendPrefix(elem):
    name = elem.attrib['name']
    elem.attrib['name'] = prefix + name
  tree = ElementTree.parse(in_file_name)
  root = tree.getroot()
  # Root element isn't returned by any traversing methods.
  if root.tag == 'testsuite':
    AppendPrefix(root)
  for elem in root.findall('testsuite'):
    AppendPrefix(elem)
  with open(out_file_name, 'w') as f:
    # Note that ElementTree of 2.6 doesn't write XML declaration.
    f.write('<?xml version="1.0" encoding="utf-8"?>\n')
    f.write(ElementTree.tostring(root, 'utf-8'))


class AndroidDevice(android_util.AndroidDevice):
  def __init__(self, serial, android_home):
    android_util.AndroidDevice.__init__(self, serial, android_home)

  def WaitForMount(self):
    """Wait until SD card is mounted."""
    retry = 10
    sleep = 30
    for _ in xrange(retry):
      if self._RunCommand('mount').find('/sdcard') != -1:
        self.GetLogger().info('SD card has been mounted.')
        return
      self.GetLogger().info(
          'SD card has not been mounted. Wait and retry. '
          'Don\'t worry. This is typically expected behavior.')
      time.sleep(sleep)
    raise IOError('No mounted SD card found. Something went wrong or the '
                  'emulator is too slow.')

  def CopyFile(self, host_path, remote_path, operation):
    """Copy a file between host and remote.

    Args:
      host_path: path in host side.
      remote_path: path in remote side.
      operation: 'push' or 'pull'.
        If 'push', 'adb push host_path remote_path' is executed.
        If 'pull', 'adb pull remote_path host_path' is executed.
    """
    if operation == 'push':
      command_args = [os.path.join(self._android_home, 'platform-tools', 'adb'),
                      '-s', self.serial, 'push', host_path, remote_path]
    elif operation == 'pull':
      command_args = [os.path.join(self._android_home, 'platform-tools', 'adb'),
                      '-s', self.serial, 'pull', remote_path, host_path]
    else:
      raise ValueError('operation parameter must be push or pull but '
                       '%s is given.' % operation)
    self.GetLogger().info('Copying at %s: %s', self.serial, command_args)
    process = subprocess.Popen(command_args)
    if process.wait() == 0:
      return
    raise IOError(
        'Failed to copy a file: %s to %s' % (host_path, remote_path))

  def _VerifyResultXMLFile(self, xml_path, test_name):
    test_suites = gtest_report.GetFromXMLFile(xml_path)
    if not test_suites:
      error_message = ('[FAIL] Result XML file for %s is invalid; %s' %
                       (test_name, xml_path))
    else:
      if test_suites.fail_num:
        self.GetLogger().warning('[FAIL] %d of test failures for %s are found',
                                 test_suites.fail_num, test_name)
        error_message = test_suites.GetErrorSummary()
      else:
        self.GetLogger().info('[ OK ] All tests for %s succeeded.', test_name)
        error_message = None
    return error_message

  def _CopyAndVerifyResult(
      self, test_name, remote_result_path, host_result_path):
    try:
      self.CopyFile(host_path=host_result_path,
                    remote_path=remote_result_path,
                    operation='pull')
      self.GetLogger().info('[ OK ] %s result file is successfully pulled.',
                            test_name)
      error_message = self._VerifyResultXMLFile(host_result_path, test_name)
    except IOError:
      self.GetLogger().warning('[FAIL] %s result file is not pulled.',
                               test_name)
      error_message = ('[FAIL] Result file does not exist. '
                       'The process might crash: %s' % test_name)
    if error_message:
      self.GetLogger().warning(error_message)
    return error_message

  def RunOneTest(self, test_bin_dir, test_name, remote_dir,
                 output_report_dir):
    """Execute each test."""
    try:
      prefix = '%s::' % (self._GetAvdName())
      host_path = os.path.join(test_bin_dir, test_name)
      remote_path = os.path.join(remote_dir, test_name)
      remote_report_file_name = '%s.xml' % test_name
      output_report_file_name = '%s%s.xml' % (prefix, test_name)
      if output_report_dir:
        output_report_path = os.path.join(output_report_dir,
                                          output_report_file_name)
      else:
        output_report_path = os.tmpnam()

      # Create default test report file.
      CreateDefaultReportFile(output_report_path, test_name, prefix)

      # Copy the binary file, run the test, and clean up the executable.
      self.CopyFile(host_path=host_path,
                    remote_path=remote_path,
                    operation='push')
      remote_report_path = os.path.abspath(
          os.path.join(remote_dir, remote_report_file_name))
      # We should append colored_log=false to suppress escape sequences on
      # continuous build.
      command = ['cd', remote_dir, ';',
                 './' + test_name, '--test_srcdir=.', '--logtostderr',
                 '--gunit_output=xml:%s' % remote_report_path,
                 '--colored_log=false']
      self._RunCommand(*command)
      temporal_report_path = os.tmpnam()
      error_message = self._CopyAndVerifyResult(
          test_name, remote_report_path, temporal_report_path)
      # Successfully the result file is pulled.
      if not error_message:
        # Append prefix to testsuite name.
        # Otherwise duplicate testsuites name will be generated finally.
        AppendPrefixToSuiteName(temporal_report_path, output_report_path,
                                prefix)
      return error_message
    finally:
      if remote_path:
        self._RunCommand('rm', remote_path)
      if remote_report_path:
        self._RunCommand('rm', remote_report_path)

  def SetUpTest(self, device, mount_point, remote_dir,
                dictionary_data, connection_data, connection_text_data,
                test_connection_data, test_connection_text_data,
                mozc_data_dir):
    """Set up the android to run tests."""
    self.WaitForMount()
    # Now, the binary size of unittests are getting bigger and actually,
    # some of them exceed the /data/data/... quota.
    # So we'll use sdcard, instead. Unfortunately, sdcard has noexec
    # attribute
    # by default, so we remove it by remounting.
    self._RunCommand('mount', '-o', 'remount', device, mount_point)
    # Some tests depend on dictionary data. In the product, the
    # data is set at jni loading time, but it is necessary to somehow
    # set the data in native tests. So, copy the dictionary data to the
    # emulator.
    self.CopyFile(host_path=dictionary_data,
                  remote_path=os.path.join(remote_dir,
                                           'embedded_data', 'dictionary_data'),
                  operation='push')
    self.CopyFile(host_path=connection_data,
                  remote_path=os.path.join(remote_dir,
                                           'embedded_data', 'connection_data'),
                  operation='push')
    self.CopyFile(host_path=connection_text_data,
                  remote_path=os.path.join(remote_dir,
                                           'data_manager', 'android',
                                           'connection_single_column.txt'),
                  operation='push')
    self.CopyFile(host_path=test_connection_data,
                  remote_path=os.path.join(remote_dir,
                                           'data_manager', 'testing',
                                           'connection_data.data'),
                  operation='push')
    self.CopyFile(host_path=test_connection_text_data,
                  remote_path=os.path.join(remote_dir,
                                           'data_manager', 'testing',
                                           'connection_single_column.txt'),
                  operation='push')
    # mozc_data_dir contains both generated .h files and test data.
    # We want only test data and they are in mozc_data_dir/data.
    # TODO(matsuzakit): Split generated .h files and test data
    #                   into separate directories.
    self.CopyFile(host_path=os.path.join(mozc_data_dir, 'data'),
                  remote_path=os.path.join(remote_dir, 'data'),
                  operation='push')

  def TearDownTest(self, remote_dir):
    self._RunCommand('rm', '-r', remote_dir)

  def RunNativeTests(self, options, abi, binaries):
    self.GetLogger().info('[NATIVE] Testing device=%s', self.serial)
    if not self.IsAcceptableAbi(abi):
      self.GetLogger().info('ABI %s is not compatible with built executables.',
                            abi)
      return []
    if int(self.GetProperty('ro.build.version.sdk')) <= 15:
      self.GetLogger().info('The device does not support PIE so skip testing.')
      return []
    try:
      error_messages = []
      self.SetUpTest(options.remote_device, options.remote_mount_point,
                     options.remote_dir,
                     options.mozc_dictionary_data_file,
                     options.mozc_connection_data_file,
                     options.mozc_connection_text_data_file,
                     options.mozc_test_connection_data_file,
                     options.mozc_test_connection_text_data_file,
                     options.mozc_data_dir)
      if options.testcase:
        test_list = options.testcase.split(',')
      else:
        test_list = None
      self.GetLogger().info('[NATIVE] Testing device=%s, abi=%s',
                            self.serial, abi)
      for test in binaries:
        if test_list and test not in test_list:
          continue
        self.GetLogger().info('[NATIVE] Testing device=%s, abi=%s, test=%s',
                              self.serial, abi, test)
        error_message = self.RunOneTest(options.test_bin_dir, test,
                                        options.remote_dir,
                                        options.output_report_dir)
        if error_message:
          error_messages.append(error_message)
      self.TearDownTest(options.remote_dir)
      return error_messages
    except Exception as e:  # pylint: disable=broad-except
      # Catches all the exceptions and returns string instead.
      # If an exception is thrown, multiprocessing module
      # complains because exceptions might not be able to be pickled.
      return [str(e)]

  def RunJavaTests(self, output_report_dir, configuration,
                   app_package_name, abi):
    try:
      if not self.IsAcceptableAbi(abi):
        self.GetLogger().info(
            'ABI %s is not compatible with built executables.', abi)
        return []
      self.GetLogger().info('[JAVA] Testing device=%s', self.serial)
      prefix = '%s::' % self._GetAvdName()
      report_file_name_remote = 'gtest-report.xml'
      report_file_name_host = prefix + 'java_layer.xml'
      output_report_path = os.path.join(output_report_dir,
                                        report_file_name_host)
      CreateDefaultReportFile(output_report_path, 'JUnit all tests', prefix)
      # Run 'run-tests' target on specified device.
      # This target does build (testee and tester), install (both) and run.
      args = ['ant', 'run-tests',
              '-Dadb.device.arg=-s %s' % self.serial,
              '-Dgyp.build_type=%s' % configuration]
      process = subprocess.Popen(args, cwd='tests')
      process.wait()
      if process.wait() != 0:
        return '[FAIL] [JAVA] run_test target fails'

      remote_report_path = os.path.join('data', 'data',
                                        app_package_name,
                                        report_file_name_remote)
      try:
        temporal_report_path = os.tmpnam()
        self.CopyFile(host_path=temporal_report_path,
                      remote_path=remote_report_path,
                      operation='pull')
        self.GetLogger().info('[ OK ] Java result file is successfully pulled.')
        # Append prefix to testsuite name.
        # Otherwise duplicate testsuites name will be generated finally.
        AppendPrefixToSuiteName(temporal_report_path, output_report_path,
                                prefix)
        # XML file verification is omitted because
        # - Java's report XML doesn't fit verifier's expectation.
      except IOError:
        self.GetLogger().warning('[FAIL] Java result file is not pulled.')
        return '[FAIL] Result file does not exist. The process might crash.'

      # TODO(matsuzakit): Verify reporting XML file here.
      # gtest_report.GetFromXMLFile() is not applicable becuase of
      # format difference.
      return None
    except Exception as e:  # pylint: disable=broad-except
      # Catches all the exceptions and returns string instead.
      # If an exception is thrown, multiprocessing module
      # complains because exceptions might not be able to be pickled.
      return str(e)

  @staticmethod
  def GetDevices(android_home):
    return [AndroidDevice(super_device.serial, android_home)
            for super_device in
            android_util.AndroidDevice.GetDevices(android_home)]


def CreateDefaultReportFile(output_report_path, test_name, prefix):
  # Create default test report file.
  # It will be used as the result of the test if the test crashes.
  with open(output_report_path, 'w') as f:
    f.write("""<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="%s%s" tests="1" errors="1">
  <testcase name="No reporting XML">
    <error message="No reporting XML has been generated. Process crash?" />
  </testcase>
</testsuite>""" % (prefix, test_name))


def RunTest(device, options, binaries):
  error_messages = []
  if options.run_native_test:
    native_error_messages = device.RunNativeTests(options, options.abi,
                                                  binaries)
    if native_error_messages:
      error_messages.extend(native_error_messages)
  if options.run_java_test:
    error_message = device.RunJavaTests(options.output_report_dir,
                                        options.configuration,
                                        options.app_package_name,
                                        options.abi)
    if error_message:
      error_messages.append(error_message)
  return '\n'.join(error_messages)


def main():
  # Enable logging.info.
  logging.getLogger().setLevel(logging.INFO)

  options = ParseArgs()

  if not options.android_home:
    logging.error('--android_home option must be specified.')
    os.exit(1)

  if options.run_native_test:
    binaries = FindTestBinaries(options.test_bin_dir)
    logging.info(binaries)
  else:
    binaries = None

  # Prepare reporting directory.
  if options.output_report_dir:
    options.output_report_dir = os.path.abspath(options.output_report_dir)
    try:
      os.makedirs(options.output_report_dir)
      logging.info('Made directory; %s', options.output_report_dir)
    except OSError as e:
      if e.errno == errno.EEXIST:
        logging.info('%s has existed already.', options.output_report_dir)
      else:
        raise

  android_home = options.android_home

  devices = AndroidDevice.GetDevices(android_home)
  logging.info('All the activated devices are %s',
               [device.serial for device in devices])
  if options.android_devices:
    using_devices = options.android_devices.split(',')
    devices = [device for device in devices if device.serial in using_devices]
    logging.info('Filtered to %s',
                 [device.serial for device in devices])

  if not devices:
    logging.info('No devices are specified. Do nothing.')
    return

  # Maximum # of devices is 10 so running them in the same time is possible.
  pool = multiprocessing.Pool(len(devices))
  results = [pool.apply_async(RunTest, [device, options, binaries])
             for device in devices]
  pool.close()
  # result.get() blocks until the test terminates.
  error_messages = [result.get() for result in results if result.get()]
  if error_messages:
    print '[FAIL] Native tests result : Test failures are found;'
    for message in error_messages:
      print message
  else:
    print '[ OK ] Native tests result : Tests scceeded.'


if __name__ == '__main__':
  main()
