Home | History | Annotate | Download | only in utils
      1 #!/usr/bin/python
      2 
      3 # Copyright (C) 2009 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #       http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 
     17 """Module for generating CTS test descriptions and test plans."""
     18 
     19 import glob
     20 import os
     21 import re
     22 import subprocess
     23 import sys
     24 import xml.dom.minidom as dom
     25 from cts import tools
     26 from multiprocessing import Pool
     27 
     28 def GetSubDirectories(root):
     29   """Return all directories under the given root directory."""
     30   return [x for x in os.listdir(root) if os.path.isdir(os.path.join(root, x))]
     31 
     32 
     33 def GetMakeFileVars(makefile_path):
     34   """Extracts variable definitions from the given make file.
     35 
     36   Args:
     37     makefile_path: Path to the make file.
     38 
     39   Returns:
     40     A dictionary mapping variable names to their assigned value.
     41   """
     42   result = {}
     43   pattern = re.compile(r'^\s*([^:#=\s]+)\s*:=\s*(.*?[^\\])$', re.MULTILINE + re.DOTALL)
     44   stream = open(makefile_path, 'r')
     45   content = stream.read()
     46   for match in pattern.finditer(content):
     47     result[match.group(1)] = match.group(2)
     48   stream.close()
     49   return result
     50 
     51 
     52 class CtsBuilder(object):
     53   """Main class for generating test descriptions and test plans."""
     54 
     55   def __init__(self, argv):
     56     """Initialize the CtsBuilder from command line arguments."""
     57     if not (len(argv) == 6 or len(argv)==7):
     58       print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath> [-pts]' % argv[0]
     59       print ''
     60       print 'testRoot:       Directory under which to search for CTS tests.'
     61       print 'ctsOutputDir:   Directory in which the CTS repository should be created.'
     62       print 'tempDir:        Directory to use for storing temporary files.'
     63       print 'androidRootDir: Root directory of the Android source tree.'
     64       print 'docletPath:     Class path where the DescriptionGenerator doclet can be found.'
     65       print '-pts:           generate plan for PTS.'
     66       sys.exit(1)
     67     self.test_root = sys.argv[1]
     68     self.out_dir = sys.argv[2]
     69     self.temp_dir = sys.argv[3]
     70     self.android_root = sys.argv[4]
     71     self.doclet_path = sys.argv[5]
     72     self.isCts = True
     73     if len(argv) ==7 and sys.argv[6] == "-pts":
     74       self.isCts = False
     75 
     76     self.test_repository = os.path.join(self.out_dir, 'repository/testcases')
     77     self.plan_repository = os.path.join(self.out_dir, 'repository/plans')
     78 
     79   def GenerateTestDescriptions(self):
     80     """Generate test descriptions for all packages."""
     81     pool = Pool(processes=2)
     82 
     83     # individually generate descriptions not following conventions
     84     pool.apply_async(GenerateSignatureCheckDescription, [self.test_repository])
     85 
     86     # generate test descriptions for android tests
     87     results = []
     88     pool.close()
     89     pool.join()
     90     return sum(map(lambda result: result.get(), results))
     91 
     92   def __WritePlan(self, plan, plan_name):
     93     print 'Generating test plan %s' % plan_name
     94     plan.Write(os.path.join(self.plan_repository, plan_name + '.xml'))
     95 
     96   def GenerateTestPlans(self):
     97     """Generate default test plans."""
     98     # TODO: Instead of hard-coding the plans here, use a configuration file,
     99     # such as test_defs.xml
    100     packages = []
    101     descriptions = sorted(glob.glob(os.path.join(self.test_repository, '*.xml')))
    102     for description in descriptions:
    103       doc = tools.XmlFile(description)
    104       packages.append(doc.GetAttr('TestPackage', 'appPackageName'))
    105 
    106     if not self.isCts: # PTS
    107       plan = tools.TestPlan(packages)
    108       plan.Include('.*')
    109       plan.Exclude(r'android\.tests\.sigtest')
    110       self.__WritePlan(plan, 'PTS')
    111       return
    112 
    113     plan = tools.TestPlan(packages)
    114     plan.Exclude('android\.performance.*')
    115     self.__WritePlan(plan, 'CTS')
    116     self.__WritePlan(plan, 'CTS-TF')
    117 
    118     plan.Exclude(r'android\.tests\.sigtest')
    119     plan.Exclude(r'android\.core.*')
    120     self.__WritePlan(plan, 'Android')
    121 
    122     plan = tools.TestPlan(packages)
    123     plan.Include(r'android\.core\.tests.*')
    124     self.__WritePlan(plan, 'Java')
    125 
    126     plan = tools.TestPlan(packages)
    127     plan.Include(r'android\.core\.vm-tests-tf')
    128     self.__WritePlan(plan, 'VM-TF')
    129 
    130     plan = tools.TestPlan(packages)
    131     plan.Include(r'android\.tests\.sigtest')
    132     self.__WritePlan(plan, 'Signature')
    133 
    134     plan = tools.TestPlan(packages)
    135     plan.Include(r'android\.tests\.appsecurity')
    136     self.__WritePlan(plan, 'AppSecurity')
    137 
    138     # hard-coded white list for PDK plan
    139     plan.Exclude('.*')
    140     plan.Include('android\.bluetooth')
    141     plan.Include('android\.graphics.*')
    142     plan.Include('android\.hardware')
    143     plan.Include('android\.media.*')
    144     plan.Include('android\.net')
    145     plan.Include('android\.opengl.*')
    146     plan.Include('android\.renderscript')
    147     plan.Include('android\.telephony')
    148     plan.Include('android\.nativemedia.*')
    149     self.__WritePlan(plan, 'PDK')
    150 
    151 def LogGenerateDescription(name):
    152   print 'Generating test description for package %s' % name
    153 
    154 def GenerateSignatureCheckDescription(test_repository):
    155   """Generate the test description for the signature check."""
    156   LogGenerateDescription('android.tests.sigtest')
    157   package = tools.TestPackage('SignatureTest', 'android.tests.sigtest')
    158   package.AddAttribute('appNameSpace', 'android.tests.sigtest')
    159   package.AddAttribute('signatureCheck', 'true')
    160   package.AddAttribute('runner', '.InstrumentationRunner')
    161   package.AddTest('android.tests.sigtest.SignatureTest.signatureTest')
    162   description = open(os.path.join(test_repository, 'SignatureTest.xml'), 'w')
    163   package.WriteDescription(description)
    164   description.close()
    165 
    166 if __name__ == '__main__':
    167   builder = CtsBuilder(sys.argv)
    168   if builder.isCts:
    169     result = builder.GenerateTestDescriptions()
    170     if result != 0:
    171       sys.exit(result)
    172   builder.GenerateTestPlans()
    173 
    174