blob: cb70c541b2a89af2e543d38bae7e2a3f2885d675 [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
Unsuk Jung2a692d12013-09-29 20:57:32 -070022import shutil
Phil Dubach0d6ef062009-08-12 18:13:16 -070023import subprocess
24import sys
25import xml.dom.minidom as dom
26from cts import tools
Brian Muramatsu9157e0a2011-04-05 18:06:15 -070027from multiprocessing import Pool
Phil Dubach0d6ef062009-08-12 18:13:16 -070028
29def GetSubDirectories(root):
30 """Return all directories under the given root directory."""
31 return [x for x in os.listdir(root) if os.path.isdir(os.path.join(root, x))]
32
33
34def GetMakeFileVars(makefile_path):
35 """Extracts variable definitions from the given make file.
36
37 Args:
38 makefile_path: Path to the make file.
39
40 Returns:
41 A dictionary mapping variable names to their assigned value.
42 """
43 result = {}
44 pattern = re.compile(r'^\s*([^:#=\s]+)\s*:=\s*(.*?[^\\])$', re.MULTILINE + re.DOTALL)
45 stream = open(makefile_path, 'r')
46 content = stream.read()
47 for match in pattern.finditer(content):
48 result[match.group(1)] = match.group(2)
49 stream.close()
50 return result
51
52
53class CtsBuilder(object):
54 """Main class for generating test descriptions and test plans."""
55
56 def __init__(self, argv):
57 """Initialize the CtsBuilder from command line arguments."""
Keun young Parkd93d0d12013-01-10 14:11:35 -080058 if len(argv) != 6:
59 print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath>' % argv[0]
Phil Dubach0d6ef062009-08-12 18:13:16 -070060 print ''
61 print 'testRoot: Directory under which to search for CTS tests.'
62 print 'ctsOutputDir: Directory in which the CTS repository should be created.'
63 print 'tempDir: Directory to use for storing temporary files.'
64 print 'androidRootDir: Root directory of the Android source tree.'
65 print 'docletPath: Class path where the DescriptionGenerator doclet can be found.'
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
73 self.test_repository = os.path.join(self.out_dir, 'repository/testcases')
74 self.plan_repository = os.path.join(self.out_dir, 'repository/plans')
Unsuk Jung2a692d12013-09-29 20:57:32 -070075
76 #dirty hack to copy over prepopulated CTS test plans, stable vs flaky, for autoCTS
Unsuk Jung08d97f92013-09-29 22:40:22 -070077 self.definedplans_repository = os.path.join(self.android_root, 'cts/tests/plans')
Phil Dubach0d6ef062009-08-12 18:13:16 -070078
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'))
Keun young Park965d1912013-02-08 11:37:16 -0800105 # sort the list to give the same sequence based on name
106 packages.sort()
Phil Dubach0d6ef062009-08-12 18:13:16 -0700107
108 plan = tools.TestPlan(packages)
Tsu Chiang Chuangd4cce3b2011-05-12 12:19:54 -0700109 plan.Exclude('android\.performance.*')
Brian Muramatsu87ff4df2011-12-16 11:41:17 -0800110 self.__WritePlan(plan, 'CTS')
Brian Muramatsu89ae08c2012-01-03 10:55:02 -0800111 self.__WritePlan(plan, 'CTS-TF')
Tsu Chiang Chuangd4cce3b2011-05-12 12:19:54 -0700112
Keun young Parkd93d0d12013-01-10 14:11:35 -0800113 plan = tools.TestPlan(packages)
Keun young Parkd93d0d12013-01-10 14:11:35 -0800114 plan.Exclude('android\.performance.*')
Guru Nagarajan55f10db2013-06-03 13:50:37 -0700115 plan.Exclude('android\.media\.cts\.StreamingMediaPlayerTest.*')
116 # Test plan to not include media streaming tests
117 self.__WritePlan(plan, 'CTS-No-Media-Stream')
118
119 plan = tools.TestPlan(packages)
120 plan.Exclude('android\.performance.*')
Keun young Parkd93d0d12013-01-10 14:11:35 -0800121 self.__WritePlan(plan, 'SDK')
122
Phil Dubach0d6ef062009-08-12 18:13:16 -0700123 plan.Exclude(r'android\.tests\.sigtest')
124 plan.Exclude(r'android\.core.*')
125 self.__WritePlan(plan, 'Android')
126
127 plan = tools.TestPlan(packages)
128 plan.Include(r'android\.core\.tests.*')
Tsu Chiang Chuangd192e6b2012-10-24 16:48:03 -0700129 plan.Exclude(r'android\.core\.tests\.libcore.\package.\harmony*')
Phil Dubach0d6ef062009-08-12 18:13:16 -0700130 self.__WritePlan(plan, 'Java')
131
Tsu Chiang Chuangd192e6b2012-10-24 16:48:03 -0700132 # TODO: remove this once the tests are fixed and merged into Java plan above.
133 plan = tools.TestPlan(packages)
134 plan.Include(r'android\.core\.tests\.libcore.\package.\harmony*')
135 self.__WritePlan(plan, 'Harmony')
136
Phil Dubach0d6ef062009-08-12 18:13:16 -0700137 plan = tools.TestPlan(packages)
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700138 plan.Include(r'android\.core\.vm-tests-tf')
139 self.__WritePlan(plan, 'VM-TF')
140
141 plan = tools.TestPlan(packages)
Phil Dubach0d6ef062009-08-12 18:13:16 -0700142 plan.Include(r'android\.tests\.sigtest')
143 self.__WritePlan(plan, 'Signature')
144
145 plan = tools.TestPlan(packages)
Phil Dubach60680482009-08-19 10:13:23 -0700146 plan.Include(r'android\.tests\.appsecurity')
147 self.__WritePlan(plan, 'AppSecurity')
148
Keun young Parkff194172012-08-14 17:56:11 -0700149 # hard-coded white list for PDK plan
150 plan.Exclude('.*')
keunyoungc767cba2013-04-03 14:50:58 -0700151 plan.Include('android\.aadb')
Keun young Parkff194172012-08-14 17:56:11 -0700152 plan.Include('android\.bluetooth')
153 plan.Include('android\.graphics.*')
154 plan.Include('android\.hardware')
keunyoungde519462013-03-21 12:06:42 -0700155 plan.Include('android\.media')
156 plan.Exclude('android\.mediastress')
Keun young Parkff194172012-08-14 17:56:11 -0700157 plan.Include('android\.net')
158 plan.Include('android\.opengl.*')
159 plan.Include('android\.renderscript')
160 plan.Include('android\.telephony')
161 plan.Include('android\.nativemedia.*')
Stuart Scotta132af62013-11-07 10:30:32 -0800162 plan.Include('com\.android\.cts\..*')#TODO(stuartscott): Should PDK have all these?
163 #TODO(stuartscott): Maybe move away from com.android.* to android.* - less typing
Keun young Parkff194172012-08-14 17:56:11 -0700164 self.__WritePlan(plan, 'PDK')
165
Unsuk Jung2a692d12013-09-29 20:57:32 -0700166 #dirty hack to copy over pre-populated CTS plans - flaky vs stable - to streamline autoCTS
Unsuk Jung08d97f92013-09-29 22:40:22 -0700167 shutil.copyfile(os.path.join(self.definedplans_repository, 'CTS-flaky.xml'),
Unsuk Jung2a692d12013-09-29 20:57:32 -0700168 os.path.join(self.plan_repository, 'CTS-flaky.xml'))
Unsuk Jung08d97f92013-09-29 22:40:22 -0700169 shutil.copyfile(os.path.join(self.definedplans_repository, 'CTS-stable.xml'),
Unsuk Jung2a692d12013-09-29 20:57:32 -0700170 os.path.join(self.plan_repository, 'CTS-stable.xml'))
171
Brian Muramatsu9157e0a2011-04-05 18:06:15 -0700172def LogGenerateDescription(name):
173 print 'Generating test description for package %s' % name
174
175def GenerateSignatureCheckDescription(test_repository):
176 """Generate the test description for the signature check."""
177 LogGenerateDescription('android.tests.sigtest')
178 package = tools.TestPackage('SignatureTest', 'android.tests.sigtest')
179 package.AddAttribute('appNameSpace', 'android.tests.sigtest')
180 package.AddAttribute('signatureCheck', 'true')
181 package.AddAttribute('runner', '.InstrumentationRunner')
Stuart Scottc09a2e02013-11-15 13:03:29 -0800182 package.AddTest('android.tests.sigtest.SignatureTest.testSignature')
Brian Muramatsu9157e0a2011-04-05 18:06:15 -0700183 description = open(os.path.join(test_repository, 'SignatureTest.xml'), 'w')
184 package.WriteDescription(description)
185 description.close()
186
Phil Dubach0d6ef062009-08-12 18:13:16 -0700187if __name__ == '__main__':
188 builder = CtsBuilder(sys.argv)
Keun young Parkd93d0d12013-01-10 14:11:35 -0800189 result = builder.GenerateTestDescriptions()
190 if result != 0:
191 sys.exit(result)
Phil Dubach0d6ef062009-08-12 18:13:16 -0700192 builder.GenerateTestPlans()
Keun young Park3769d332012-08-29 10:16:37 -0700193