blob: 8e23f131217f031b3bf1e1499f33ec31806daeb9 [file] [log] [blame]
Phil Dubachec19a572009-08-21 15:20:13 -07001#!/usr/bin/python
Phil Dubach0d6ef062009-08-12 18:13:16 -07002
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
Brian Muramatsu9157e0a2011-04-05 18:06:15 -070026from multiprocessing import Pool
Phil Dubach0d6ef062009-08-12 18:13:16 -070027
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."""
Keun young Park3769d332012-08-29 10:16:37 -070057 if not (len(argv) == 6 or len(argv)==7):
58 print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath> [-pts]' % argv[0]
Phil Dubach0d6ef062009-08-12 18:13:16 -070059 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.'
Keun young Park3769d332012-08-29 10:16:37 -070065 print '-pts: generate plan for PTS.'
Phil Dubach0d6ef062009-08-12 18:13:16 -070066 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]
Keun young Park3769d332012-08-29 10:16:37 -070072 self.isCts = True
73 if len(argv) ==7 and sys.argv[6] == "-pts":
74 self.isCts = False
Phil Dubach0d6ef062009-08-12 18:13:16 -070075
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
Phil Dubach0d6ef062009-08-12 18:13:16 -070079 def GenerateTestDescriptions(self):
80 """Generate test descriptions for all packages."""
Brian Muramatsu5df641c2011-12-28 15:46:57 -080081 pool = Pool(processes=2)
Brian Muramatsu9157e0a2011-04-05 18:06:15 -070082
Phil Dubach0d6ef062009-08-12 18:13:16 -070083 # individually generate descriptions not following conventions
Brian Muramatsu9157e0a2011-04-05 18:06:15 -070084 pool.apply_async(GenerateSignatureCheckDescription, [self.test_repository])
Phil Dubach0d6ef062009-08-12 18:13:16 -070085
86 # generate test descriptions for android tests
Brian Muramatsubdcfc7c2011-12-01 14:32:02 -080087 results = []
Brian Muramatsu9157e0a2011-04-05 18:06:15 -070088 pool.close()
89 pool.join()
Brian Muramatsubdcfc7c2011-12-01 14:32:02 -080090 return sum(map(lambda result: result.get(), results))
Phil Dubach0d6ef062009-08-12 18:13:16 -070091
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 = []
Phil Dubach8dcedfe2009-08-20 16:10:39 -0700101 descriptions = sorted(glob.glob(os.path.join(self.test_repository, '*.xml')))
Phil Dubach0d6ef062009-08-12 18:13:16 -0700102 for description in descriptions:
103 doc = tools.XmlFile(description)
104 packages.append(doc.GetAttr('TestPackage', 'appPackageName'))
105
Keun young Park3769d332012-08-29 10:16:37 -0700106 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
Phil Dubach0d6ef062009-08-12 18:13:16 -0700113 plan = tools.TestPlan(packages)
Tsu Chiang Chuangd4cce3b2011-05-12 12:19:54 -0700114 plan.Exclude('android\.performance.*')
Brian Muramatsu87ff4df2011-12-16 11:41:17 -0800115 self.__WritePlan(plan, 'CTS')
Brian Muramatsu89ae08c2012-01-03 10:55:02 -0800116 self.__WritePlan(plan, 'CTS-TF')
Tsu Chiang Chuangd4cce3b2011-05-12 12:19:54 -0700117
Phil Dubach0d6ef062009-08-12 18:13:16 -0700118 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)
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700127 plan.Include(r'android\.core\.vm-tests-tf')
128 self.__WritePlan(plan, 'VM-TF')
129
130 plan = tools.TestPlan(packages)
Phil Dubach0d6ef062009-08-12 18:13:16 -0700131 plan.Include(r'android\.tests\.sigtest')
132 self.__WritePlan(plan, 'Signature')
133
134 plan = tools.TestPlan(packages)
Phil Dubach60680482009-08-19 10:13:23 -0700135 plan.Include(r'android\.tests\.appsecurity')
136 self.__WritePlan(plan, 'AppSecurity')
137
Keun young Parkff194172012-08-14 17:56:11 -0700138 # 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
Brian Muramatsu9157e0a2011-04-05 18:06:15 -0700151def LogGenerateDescription(name):
152 print 'Generating test description for package %s' % name
153
154def 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
Phil Dubach0d6ef062009-08-12 18:13:16 -0700166if __name__ == '__main__':
167 builder = CtsBuilder(sys.argv)
Keun young Park34246562012-09-18 11:18:20 -0700168 if builder.isCts:
169 result = builder.GenerateTestDescriptions()
170 if result != 0:
171 sys.exit(result)
Phil Dubach0d6ef062009-08-12 18:13:16 -0700172 builder.GenerateTestPlans()
Keun young Park3769d332012-08-29 10:16:37 -0700173