#!/usr/bin/python

# Copyright (C) 2009 The Android Open Source Project
#
# 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.

"""Module for generating CTS test descriptions and test plans."""

import glob
import os
import re
import subprocess
import sys
import xml.dom.minidom as dom
from cts import tools


def GetSubDirectories(root):
  """Return all directories under the given root directory."""
  return [x for x in os.listdir(root) if os.path.isdir(os.path.join(root, x))]


def GetMakeFileVars(makefile_path):
  """Extracts variable definitions from the given make file.

  Args:
    makefile_path: Path to the make file.

  Returns:
    A dictionary mapping variable names to their assigned value.
  """
  result = {}
  pattern = re.compile(r'^\s*([^:#=\s]+)\s*:=\s*(.*?[^\\])$', re.MULTILINE + re.DOTALL)
  stream = open(makefile_path, 'r')
  content = stream.read()
  for match in pattern.finditer(content):
    result[match.group(1)] = match.group(2)
  stream.close()
  return result


class CtsBuilder(object):
  """Main class for generating test descriptions and test plans."""

  def __init__(self, argv):
    """Initialize the CtsBuilder from command line arguments."""
    if not len(argv) == 6:
      print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath>' % argv[0]
      print ''
      print 'testRoot:       Directory under which to search for CTS tests.'
      print 'ctsOutputDir:   Directory in which the CTS repository should be created.'
      print 'tempDir:        Directory to use for storing temporary files.'
      print 'androidRootDir: Root directory of the Android source tree.'
      print 'docletPath:     Class path where the DescriptionGenerator doclet can be found.'
      sys.exit(1)
    self.test_root = sys.argv[1]
    self.out_dir = sys.argv[2]
    self.temp_dir = sys.argv[3]
    self.android_root = sys.argv[4]
    self.doclet_path = sys.argv[5]

    self.test_repository = os.path.join(self.out_dir, 'repository/testcases')
    self.plan_repository = os.path.join(self.out_dir, 'repository/plans')

  def __LogGenerateDescription(self, name):
    print 'Generating test description for package %s' % name

  def RunDescriptionGeneratorDoclet(self, source_root, output_file):
    """Generate a test package description by running the DescriptionGenerator doclet.

    Args:
      source_root: Directory under which tests should be searched.
      output_file: Name of the file where the description gets written.

    Returns:
      The exit code of the DescriptionGenerator doclet run.
    """
    # Make sure sourceRoot is relative to  self.android_root
    source_root = self.RelPath(source_root, self.android_root)

    # To determine whether a class is a JUnit test, the Doclet needs to have all intermediate
    # subclasses of TestCase as well as the JUnit framework itself on the source path.
    # Annotation classes are also required, since test annotations go into the description.
    source_path = [
        'frameworks/base/core/java',            # android test classes
        'frameworks/base/test-runner/src',      # test runner
        'libcore/junit/src/main/java',          # junit classes
        'development/tools/hosttestlib/src',    # hosttestlib TestCase extensions
        'libcore/dalvik/src/main/java',         # test annotations
        'cts/libs/annotation/src',              # cts annotations
        'cts/tests/src',                        # cts test stubs
        source_root                             # the source for this package
    ]
    source_path = [os.path.join(self.android_root, x) for x in source_path]
    cmd = ('javadoc -o %s -J-Xmx512m -quiet -doclet DescriptionGenerator -docletpath %s'
           ' -sourcepath %s ') % (output_file, self.doclet_path, ':'.join(source_path))
    sources = []

    def AddFile(sources, folder, names):
      """Find *.java."""
      sources.extend([os.path.join(folder, name) for name in names if name.endswith('.java')])

    os.path.walk(os.path.join(self.android_root, source_root), AddFile, sources)
    cmd += ' '.join(sources)
    proc = subprocess.Popen(cmd, shell=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
    # read and discard any output
    proc.communicate()
    # wait for process to terminate and return exit value
    return proc.wait()

  def GenerateSignatureCheckDescription(self):
    """Generate the test description for the signature check."""
    self.__LogGenerateDescription('android.tests.sigtest')
    package = tools.TestPackage('SignatureTest', 'android.tests.sigtest')
    package.AddAttribute('appNameSpace', 'android.tests.sigtest')
    package.AddAttribute('signatureCheck', 'true')
    package.AddAttribute('runner', '.InstrumentationRunner')
    package.AddTest('android.tests.sigtest.SignatureTest.signatureTest')
    description = open(os.path.join(self.test_repository, 'SignatureTest.xml'), 'w')
    package.WriteDescription(description)
    description.close()

  def GenerateReferenceAppDescription(self):
    """Generate the test description for the reference app tests."""
    self.__LogGenerateDescription('android.apidemos.cts')
    package = tools.TestPackage('ApiDemosReferenceTest', 'android.apidemos.cts')
    package.AddAttribute('appNameSpace', 'android.apidemos.cts')
    package.AddAttribute('packageToTest', 'com.example.android.apis')
    package.AddAttribute('apkToTestName', 'ApiDemos')
    package.AddAttribute('runner', 'android.test.InstrumentationTestRunner')
    package.AddAttribute('referenceAppTest', 'true')
    package.AddTest('android.apidemos.cts.ApiDemosTest.testNumberOfItemsInListView')
    description = open(os.path.join(self.test_repository, 'ApiDemosReferenceTest.xml'), 'w')
    package.WriteDescription(description)
    description.close()

  def GenerateAppSecurityDescription(self):
    """Generate the test description for the application security tests."""
    test_root = 'cts/tests/appsecurity-tests'
    makefile_name = os.path.join(test_root, 'Android.mk')
    makefile_vars = GetMakeFileVars(makefile_name)
    name = makefile_vars['LOCAL_MODULE']
    package_name = 'android.tests.appsecurity'
    self.__LogGenerateDescription(package_name)
    temp_desc = os.path.join(self.temp_dir, 'description.xml')
    self.RunDescriptionGeneratorDoclet(os.path.join(test_root, 'src'), temp_desc)
    doc = dom.parse(temp_desc)
    test_description = doc.getElementsByTagName('TestPackage')[0]
    test_description.setAttribute('name', package_name)
    test_description.setAttribute('appPackageName', package_name)
    test_description.setAttribute('hostSideOnly', 'true')
    test_description.setAttribute('jarPath', name + '.jar')
    description = open(os.path.join(self.test_repository, package_name + '.xml'), 'w')
    doc.writexml(description, addindent='    ', encoding='UTF-8')
    description.close()

  @staticmethod
  def RelPath(path, start=os.getcwd()):
    """Get a relative version of a path.

    This is equivalent to os.path.relpath, which is only available since Python 2.6.

    Args:
      path: The path to transform.
      start: The base path. Defaults to the current working directory.

    Returns:
      A transformed path that is relative to start.
    """
    path_dirs = os.path.abspath(path).split(os.path.sep)
    start_dirs = os.path.abspath(start).split(os.path.sep)

    num_common = len(os.path.commonprefix([start_dirs, path_dirs]))

    result_dirs = ['..'] * (len(start_dirs) - num_common) + path_dirs[num_common:]
    if result_dirs:
      return os.path.join(*result_dirs)
    return start

  def GenerateTestDescriptions(self):
    """Generate test descriptions for all packages."""
    # individually generate descriptions not following conventions
    self.GenerateSignatureCheckDescription()
    self.GenerateReferenceAppDescription()
    self.GenerateAppSecurityDescription()

    # generate test descriptions for android tests
    android_packages = GetSubDirectories(self.test_root)
    for package in android_packages:
      app_package_name = 'android.' + package
      package_root = os.path.join(self.test_root, package)

      makefile_name = os.path.join(package_root, 'Android.mk')
      if not os.path.exists(makefile_name):
        print 'Skipping directory "%s" due to missing Android.mk' % package_root
        continue
      makefile_vars = GetMakeFileVars(makefile_name)

      manifest_name = os.path.join(package_root, 'AndroidManifest.xml')
      if not os.path.exists(manifest_name):
        print 'Skipping directory "%s" due to missing AndroidManifest.xml' % package_root
        continue
      manifest = tools.XmlFile(manifest_name)

      self.__LogGenerateDescription(app_package_name)

      # Run the description generator doclet to get the test package structure
      # TODO: The Doclet does not currently add all required attributes. Instead of rewriting
      # the document below, additional attributes should be passed to the Doclet as arguments.
      temp_desc = os.path.join(self.temp_dir, 'description.xml')
      self.RunDescriptionGeneratorDoclet(package_root, temp_desc)

      # obtain missing attribute values from the makefile and manifest
      package_name = makefile_vars['LOCAL_PACKAGE_NAME']
      runner = manifest.GetAndroidAttr('instrumentation', 'name')
      target_package = manifest.GetAndroidAttr('instrumentation', 'targetPackage')
      target_binary_name = makefile_vars.get('LOCAL_INSTRUMENTATION_FOR')

      # add them to the document
      doc = dom.parse(temp_desc)
      test_description = doc.getElementsByTagName('TestPackage')[0]
      test_description.setAttribute('name', package_name)
      test_description.setAttribute('runner', runner)
      test_package = manifest.GetAttr('manifest', 'package')
      test_description.setAttribute('appNameSpace', test_package)
      test_description.setAttribute('appPackageName', app_package_name)
      if not test_package == target_package:
        test_description.setAttribute('targetNameSpace', target_package)
        test_description.setAttribute('targetBinaryName', target_binary_name)
      description = open(os.path.join(self.test_repository, package_name + '.xml'), 'w')
      doc.writexml(description, addindent='    ', encoding='UTF-8')
      description.close()

  def __WritePlan(self, plan, plan_name):
    print 'Generating test plan %s' % plan_name
    plan.Write(os.path.join(self.plan_repository, plan_name + '.xml'))

  def GenerateTestPlans(self):
    """Generate default test plans."""
    # TODO: Instead of hard-coding the plans here, use a configuration file,
    # such as test_defs.xml
    packages = []
    descriptions = sorted(glob.glob(os.path.join(self.test_repository, '*.xml')))
    for description in descriptions:
      doc = tools.XmlFile(description)
      packages.append(doc.GetAttr('TestPackage', 'appPackageName'))

    plan = tools.TestPlan(packages)
    plan.Exclude('android\.performance.*')
    self.__WritePlan(plan, 'CTS')
    plan.Exclude(r'android\.tests\.sigtest')
    plan.Exclude(r'android\.core.*')
    self.__WritePlan(plan, 'Android')

    plan = tools.TestPlan(packages)
    plan.Include(r'android\.core\.tests.*')
    self.__WritePlan(plan, 'Java')

    plan = tools.TestPlan(packages)
    plan.Include(r'android\.core\.vm-tests')
    self.__WritePlan(plan, 'VM')

    plan = tools.TestPlan(packages)
    plan.Include(r'android\.tests\.sigtest')
    self.__WritePlan(plan, 'Signature')

    plan = tools.TestPlan(packages)
    plan.Include(r'android\.apidemos\.cts')
    self.__WritePlan(plan, 'RefApp')

    plan = tools.TestPlan(packages)
    plan.Include(r'android\.performance.*')
    self.__WritePlan(plan, 'Performance')

    plan = tools.TestPlan(packages)
    plan.Include(r'android\.tests\.appsecurity')
    self.__WritePlan(plan, 'AppSecurity')


if __name__ == '__main__':
  builder = CtsBuilder(sys.argv)
  builder.GenerateTestDescriptions()
  builder.GenerateTestPlans()
