• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 shutil
23import subprocess
24import sys
25import xml.dom.minidom as dom
26from cts import tools
27from multiprocessing import Pool
28
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."""
58    if len(argv) != 6:
59      print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath>' % argv[0]
60      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')
75
76    #dirty hack to copy over prepopulated CTS test plans, stable vs flaky, for autoCTS
77    self.definedplans_repository = os.path.join(self.android_root, 'cts/tests/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    # sort the list to give the same sequence based on name
106    packages.sort()
107
108    plan = tools.TestPlan(packages)
109    plan.Exclude('android\.performance.*')
110    self.__WritePlan(plan, 'CTS')
111    self.__WritePlan(plan, 'CTS-TF')
112
113    plan = tools.TestPlan(packages)
114    plan.Exclude('android\.performance.*')
115    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.*')
121    self.__WritePlan(plan, 'SDK')
122
123    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.*')
129    self.__WritePlan(plan, 'Java')
130
131    plan = tools.TestPlan(packages)
132    plan.Include(r'android\.core\.vm-tests-tf')
133    self.__WritePlan(plan, 'VM-TF')
134
135    plan = tools.TestPlan(packages)
136    plan.Include(r'android\.tests\.sigtest')
137    self.__WritePlan(plan, 'Signature')
138
139    plan = tools.TestPlan(packages)
140    plan.Include(r'android\.tests\.appsecurity')
141    self.__WritePlan(plan, 'AppSecurity')
142
143    # hard-coded white list for PDK plan
144    plan.Exclude('.*')
145    plan.Include('android\.aadb')
146    plan.Include('android\.bluetooth')
147    plan.Include('android\.graphics.*')
148    plan.Include('android\.hardware')
149    plan.Include('android\.media')
150    plan.Exclude('android\.mediastress')
151    plan.Include('android\.net')
152    plan.Include('android\.opengl.*')
153    plan.Include('android\.renderscript')
154    plan.Include('android\.telephony')
155    plan.Include('android\.nativemedia.*')
156    plan.Include('com\.android\.cts\..*')#TODO(stuartscott): Should PDK have all these?
157    #TODO(stuartscott): Maybe move away from com.android.* to android.* - less typing
158    self.__WritePlan(plan, 'PDK')
159
160    #dirty hack to copy over pre-populated CTS plans - flaky vs stable - to streamline autoCTS
161    shutil.copyfile(os.path.join(self.definedplans_repository, 'CTS-flaky.xml'),
162        os.path.join(self.plan_repository, 'CTS-flaky.xml'))
163    shutil.copyfile(os.path.join(self.definedplans_repository, 'CTS-stable.xml'),
164        os.path.join(self.plan_repository, 'CTS-stable.xml'))
165
166def LogGenerateDescription(name):
167  print 'Generating test description for package %s' % name
168
169def GenerateSignatureCheckDescription(test_repository):
170  """Generate the test description for the signature check."""
171  LogGenerateDescription('android.tests.sigtest')
172  package = tools.TestPackage('SignatureTest', 'android.tests.sigtest')
173  package.AddAttribute('appNameSpace', 'android.tests.sigtest')
174  package.AddAttribute('signatureCheck', 'true')
175  package.AddAttribute('runner', '.InstrumentationRunner')
176  package.AddTest('android.tests.sigtest.SignatureTest.testSignature')
177  description = open(os.path.join(test_repository, 'SignatureTest.xml'), 'w')
178  package.WriteDescription(description)
179  description.close()
180
181if __name__ == '__main__':
182  builder = CtsBuilder(sys.argv)
183  result = builder.GenerateTestDescriptions()
184  if result != 0:
185    sys.exit(result)
186  builder.GenerateTestPlans()
187
188