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 19import glob 20import os 21import re 22import subprocess 23import sys 24import xml.dom.minidom as dom 25from cts import tools 26from multiprocessing import Pool 27 28def 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 33def 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 52class 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: 58 print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath>' % 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 sys.exit(1) 66 self.test_root = sys.argv[1] 67 self.out_dir = sys.argv[2] 68 self.temp_dir = sys.argv[3] 69 self.android_root = sys.argv[4] 70 self.doclet_path = sys.argv[5] 71 72 self.test_repository = os.path.join(self.out_dir, 'repository/testcases') 73 self.plan_repository = os.path.join(self.out_dir, 'repository/plans') 74 75 def GenerateTestDescriptions(self): 76 """Generate test descriptions for all packages.""" 77 pool = Pool(processes=2) 78 79 # individually generate descriptions not following conventions 80 pool.apply_async(GenerateSignatureCheckDescription, [self.test_repository]) 81 82 # generate test descriptions for android tests 83 results = [] 84 pool.close() 85 pool.join() 86 return sum(map(lambda result: result.get(), results)) 87 88 def __WritePlan(self, plan, plan_name): 89 print 'Generating test plan %s' % plan_name 90 plan.Write(os.path.join(self.plan_repository, plan_name + '.xml')) 91 92 def GenerateTestPlans(self): 93 """Generate default test plans.""" 94 # TODO: Instead of hard-coding the plans here, use a configuration file, 95 # such as test_defs.xml 96 packages = [] 97 descriptions = sorted(glob.glob(os.path.join(self.test_repository, '*.xml'))) 98 for description in descriptions: 99 doc = tools.XmlFile(description) 100 packages.append(doc.GetAttr('TestPackage', 'appPackageName')) 101 102 plan = tools.TestPlan(packages) 103 plan.Exclude('android\.performance.*') 104 self.__WritePlan(plan, 'CTS') 105 self.__WritePlan(plan, 'CTS-TF') 106 107 plan.Exclude(r'android\.tests\.sigtest') 108 plan.Exclude(r'android\.core.*') 109 self.__WritePlan(plan, 'Android') 110 111 plan = tools.TestPlan(packages) 112 plan.Include(r'android\.core\.tests.*') 113 self.__WritePlan(plan, 'Java') 114 115 plan = tools.TestPlan(packages) 116 plan.Include(r'android\.core\.vm-tests-tf') 117 self.__WritePlan(plan, 'VM-TF') 118 119 plan = tools.TestPlan(packages) 120 plan.Include(r'android\.tests\.sigtest') 121 self.__WritePlan(plan, 'Signature') 122 123 plan = tools.TestPlan(packages) 124 plan.Include(r'android\.tests\.appsecurity') 125 self.__WritePlan(plan, 'AppSecurity') 126 127def LogGenerateDescription(name): 128 print 'Generating test description for package %s' % name 129 130def GenerateSignatureCheckDescription(test_repository): 131 """Generate the test description for the signature check.""" 132 LogGenerateDescription('android.tests.sigtest') 133 package = tools.TestPackage('SignatureTest', 'android.tests.sigtest') 134 package.AddAttribute('appNameSpace', 'android.tests.sigtest') 135 package.AddAttribute('signatureCheck', 'true') 136 package.AddAttribute('runner', '.InstrumentationRunner') 137 package.AddTest('android.tests.sigtest.SignatureTest.signatureTest') 138 description = open(os.path.join(test_repository, 'SignatureTest.xml'), 'w') 139 package.WriteDescription(description) 140 description.close() 141 142if __name__ == '__main__': 143 builder = CtsBuilder(sys.argv) 144 result = builder.GenerateTestDescriptions() 145 if result != 0: 146 sys.exit(result) 147 builder.GenerateTestPlans() 148