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 string
24import subprocess
25import sys
26import xml.dom.minidom as dom
27from cts import tools
28from multiprocessing import Pool
29
30def GetSubDirectories(root):
31  """Return all directories under the given root directory."""
32  return [x for x in os.listdir(root) if os.path.isdir(os.path.join(root, x))]
33
34def ReadFileLines(filePath):
35  """Reads a file and returns its contents as a line list."""
36  f = open(filePath, 'r');
37  lines = [line.strip() for line in f.readlines()]
38  f.close()
39  return lines
40
41def ReadDeqpTestList(testRoot, file):
42  """Reads a file, converts test names from deqp to CTS format, and returns
43  its contents as a line list.
44  """
45  REPO_ROOT = os.path.join(testRoot, "../../..")
46  f = open(os.path.join(REPO_ROOT, "external/deqp/android/cts", file), 'r');
47  lines = [string.join(line.strip().rsplit('.',1),'#') for line in f.readlines()]
48  f.close()
49  return lines
50
51def GetMakeFileVars(makefile_path):
52  """Extracts variable definitions from the given make file.
53
54  Args:
55    makefile_path: Path to the make file.
56
57  Returns:
58    A dictionary mapping variable names to their assigned value.
59  """
60  result = {}
61  pattern = re.compile(r'^\s*([^:#=\s]+)\s*:=\s*(.*?[^\\])$', re.MULTILINE + re.DOTALL)
62  stream = open(makefile_path, 'r')
63  content = stream.read()
64  for match in pattern.finditer(content):
65    result[match.group(1)] = match.group(2)
66  stream.close()
67  return result
68
69
70class CtsBuilder(object):
71  """Main class for generating test descriptions and test plans."""
72
73  def __init__(self, argv):
74    """Initialize the CtsBuilder from command line arguments."""
75    if len(argv) != 6:
76      print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath>' % argv[0]
77      print ''
78      print 'testRoot:       Directory under which to search for CTS tests.'
79      print 'ctsOutputDir:   Directory in which the CTS repository should be created.'
80      print 'tempDir:        Directory to use for storing temporary files.'
81      print 'androidRootDir: Root directory of the Android source tree.'
82      print 'docletPath:     Class path where the DescriptionGenerator doclet can be found.'
83      sys.exit(1)
84    self.test_root = sys.argv[1]
85    self.out_dir = sys.argv[2]
86    self.temp_dir = sys.argv[3]
87    self.android_root = sys.argv[4]
88    self.doclet_path = sys.argv[5]
89
90    self.test_repository = os.path.join(self.out_dir, 'repository/testcases')
91    self.plan_repository = os.path.join(self.out_dir, 'repository/plans')
92    self.definedplans_repository = os.path.join(self.android_root, 'cts/tests/plans')
93
94  def GenerateTestDescriptions(self):
95    """Generate test descriptions for all packages."""
96    pool = Pool(processes=2)
97
98    # generate test descriptions for android tests
99    results = []
100    pool.close()
101    pool.join()
102    return sum(map(lambda result: result.get(), results))
103
104  def __WritePlan(self, plan, plan_name):
105    print 'Generating test plan %s' % plan_name
106    plan.Write(os.path.join(self.plan_repository, plan_name + '.xml'))
107
108  def GenerateTestPlans(self):
109    """Generate default test plans."""
110    # TODO: Instead of hard-coding the plans here, use a configuration file,
111    # such as test_defs.xml
112    packages = []
113    descriptions = sorted(glob.glob(os.path.join(self.test_repository, '*.xml')))
114    for description in descriptions:
115      doc = tools.XmlFile(description)
116      packages.append(doc.GetAttr('TestPackage', 'appPackageName'))
117    # sort the list to give the same sequence based on name
118    packages.sort()
119
120    plan = tools.TestPlan(packages)
121    plan.Exclude('android\.car')
122    plan.Exclude('android\.performance.*')
123    self.__WritePlan(plan, 'CTS')
124    self.__WritePlan(plan, 'CTS-TF')
125
126    plan = tools.TestPlan(packages)
127    plan.Exclude('android\.car')
128    plan.Exclude('android\.performance.*')
129    plan.Exclude('android\.media\.cts\.StreamingMediaPlayerTest.*')
130    # Test plan to not include media streaming tests
131    self.__WritePlan(plan, 'CTS-No-Media-Stream')
132
133    plan = tools.TestPlan(packages)
134    plan.Exclude('android\.car')
135    plan.Exclude('android\.performance.*')
136    self.__WritePlan(plan, 'SDK')
137
138    plan.Exclude(r'android\.signature')
139    plan.Exclude(r'android\.core.*')
140    self.__WritePlan(plan, 'Android')
141
142    plan = tools.TestPlan(packages)
143    plan.Include(r'android\.core\.tests.*')
144    plan.Exclude(r'android\.core\.tests\.libcore\.package\.harmony*')
145    self.__WritePlan(plan, 'Java')
146
147    # TODO: remove this once the tests are fixed and merged into Java plan above.
148    plan = tools.TestPlan(packages)
149    plan.Include(r'android\.core\.tests\.libcore\.package\.harmony*')
150    self.__WritePlan(plan, 'Harmony')
151
152    plan = tools.TestPlan(packages)
153    plan.Include(r'android\.core\.vm-tests-tf')
154    self.__WritePlan(plan, 'VM-TF')
155
156    plan = tools.TestPlan(packages)
157    plan.Include(r'android\.tests\.appsecurity')
158    self.__WritePlan(plan, 'AppSecurity')
159
160    # hard-coded white list for PDK plan
161    plan.Exclude('.*')
162    plan.Include('android\.aadb')
163    plan.Include('android\.bluetooth')
164    plan.Include('android\.graphics.*')
165    plan.Include('android\.hardware')
166    plan.Include('android\.media')
167    plan.Exclude('android\.mediastress')
168    plan.Include('android\.net')
169    plan.Include('android\.opengl.*')
170    plan.Include('android\.renderscript')
171    plan.Include('android\.telephony')
172    plan.Include('android\.nativemedia.*')
173    plan.Include('com\.android\.cts\..*')#TODO(stuartscott): Should PDK have all these?
174    plan.Exclude('android\.car')
175    self.__WritePlan(plan, 'PDK')
176
177    temporarily_known_failure_tests = BuildCtsTemporarilyKnownFailureList();
178    flaky_tests = BuildCtsFlakyTestList()
179    releasekey_tests = BuildListForReleaseBuildTest()
180
181    # CTS Stable plan
182    plan = tools.TestPlan(packages)
183    plan.Exclude('android\.car')
184    plan.Exclude(r'android\.browser')
185    for package, test_list in flaky_tests.iteritems():
186      plan.ExcludeTests(package, test_list)
187    for package, test_list in releasekey_tests.iteritems():
188      plan.ExcludeTests(package, test_list)
189    self.__WritePlan(plan, 'CTS-stable')
190
191    # CTS Flaky plan - list of tests known to be flaky in lab environment
192    plan = tools.TestPlan(packages)
193    plan.Exclude('.*')
194    plan.Include(r'android\.browser')
195    for package, test_list in flaky_tests.iteritems():
196      plan.Include(package+'$')
197      plan.IncludeTests(package, test_list)
198    self.__WritePlan(plan, 'CTS-flaky')
199
200    small_tests = BuildAospSmallSizeTestList()
201    medium_tests = BuildAospMediumSizeTestList()
202    new_test_packages = BuildCtsVettedNewPackagesList()
203
204    # CTS - sub plan for public, small size tests
205    plan = tools.TestPlan(packages)
206    plan.Exclude('.*')
207    for package, test_list in small_tests.iteritems():
208      plan.Include(package+'$')
209    plan.Exclude(r'android\.browser')
210    for package, test_list in flaky_tests.iteritems():
211      plan.ExcludeTests(package, test_list)
212    for package, test_list in releasekey_tests.iteritems():
213      plan.ExcludeTests(package, test_list)
214    self.__WritePlan(plan, 'CTS-kitkat-small')
215    self.__WritePlan(plan, 'CTS-public-small')
216
217    # CTS - sub plan for public, medium size tests
218    plan = tools.TestPlan(packages)
219    plan.Exclude('.*')
220    for package, test_list in medium_tests.iteritems():
221      plan.Include(package+'$')
222    plan.Exclude(r'android\.browser')
223    for package, test_list in flaky_tests.iteritems():
224      plan.ExcludeTests(package, test_list)
225    for package, test_list in releasekey_tests.iteritems():
226      plan.ExcludeTests(package, test_list)
227    self.__WritePlan(plan, 'CTS-kitkat-medium')
228    self.__WritePlan(plan, 'CTS-public-medium')
229
230    # CTS - sub plan for hardware tests which is public, large
231    plan = tools.TestPlan(packages)
232    plan.Exclude('.*')
233    plan.Include(r'android\.hardware$')
234    plan.Exclude(r'android\.browser')
235    for package, test_list in flaky_tests.iteritems():
236      plan.ExcludeTests(package, test_list)
237    for package, test_list in releasekey_tests.iteritems():
238      plan.ExcludeTests(package, test_list)
239    self.__WritePlan(plan, 'CTS-hardware')
240
241    # CTS - sub plan for camera tests which is public, large
242    plan = tools.TestPlan(packages)
243    plan.Exclude('.*')
244    plan.Include(r'android\.camera$')
245    misc_camera_tests = BuildCtsMiscCameraList()
246    for package, test_list in misc_camera_tests.iteritems():
247      plan.Include(package+'$')
248      plan.IncludeTests(package, test_list)
249    for package, test_list in flaky_tests.iteritems():
250      plan.ExcludeTests(package, test_list)
251    for package, test_list in releasekey_tests.iteritems():
252      plan.ExcludeTests(package, test_list)
253    self.__WritePlan(plan, 'CTS-camera')
254
255    # CTS - sub plan for media tests which is public, large
256    plan = tools.TestPlan(packages)
257    plan.Exclude('.*')
258    plan.Include(r'android\.media$')
259    plan.Include(r'android\.view$')
260    plan.Exclude(r'android\.browser')
261    for package, test_list in flaky_tests.iteritems():
262      plan.ExcludeTests(package, test_list)
263    for package, test_list in releasekey_tests.iteritems():
264      plan.ExcludeTests(package, test_list)
265    self.__WritePlan(plan, 'CTS-media')
266
267    # CTS - sub plan for mediastress tests which is public, large
268    plan = tools.TestPlan(packages)
269    plan.Exclude('.*')
270    plan.Include(r'android\.mediastress$')
271    plan.Exclude(r'android\.browser')
272    for package, test_list in flaky_tests.iteritems():
273      plan.ExcludeTests(package, test_list)
274    for package, test_list in releasekey_tests.iteritems():
275      plan.ExcludeTests(package, test_list)
276    self.__WritePlan(plan, 'CTS-mediastress')
277
278    # CTS - sub plan for new tests that is vetted for L launch
279    plan = tools.TestPlan(packages)
280    plan.Exclude('.*')
281    for package, test_list in new_test_packages.iteritems():
282      plan.Include(package+'$')
283    plan.Exclude(r'android\.browser')
284    for package, test_list in flaky_tests.iteritems():
285      plan.ExcludeTests(package, test_list)
286    for package, test_list in releasekey_tests.iteritems():
287      plan.ExcludeTests(package, test_list)
288    self.__WritePlan(plan, 'CTS-l-tests')
289
290    # CTS - sub plan for tests in drawelement packages
291    plan = tools.TestPlan(packages)
292    plan.Exclude('.*')
293    plan.Include(r'com\.drawelements\.')
294    plan.IncludeTests('com.drawelements.deqp.egl', ReadDeqpTestList(self.test_root, 'mnc/egl-master.txt'))
295    plan.IncludeTests('com.drawelements.deqp.gles2', ReadDeqpTestList(self.test_root, 'mnc/gles2-master.txt'))
296    plan.IncludeTests('com.drawelements.deqp.gles3', ReadDeqpTestList(self.test_root, 'mnc/gles3-master.txt'))
297    plan.IncludeTests('com.drawelements.deqp.gles31', ReadDeqpTestList(self.test_root, 'mnc/gles31-master.txt'))
298    self.__WritePlan(plan, 'CTS-DEQP')
299
300    plan = tools.TestPlan(packages)
301    plan.Exclude('.*')
302    plan.Include(r'com\.drawelements\.')
303    plan.ExcludeTests('com.drawelements.deqp.egl', ReadDeqpTestList(self.test_root, 'mnc/egl-master.txt'))
304    plan.ExcludeTests('com.drawelements.deqp.gles2', ReadDeqpTestList(self.test_root, 'mnc/gles2-master.txt'))
305    plan.ExcludeTests('com.drawelements.deqp.gles3', ReadDeqpTestList(self.test_root, 'mnc/gles3-master.txt'))
306    plan.ExcludeTests('com.drawelements.deqp.gles31', ReadDeqpTestList(self.test_root, 'mnc/gles31-master.txt'))
307    self.__WritePlan(plan, 'CTS-DEQP-for-next-rel')
308
309    # CTS - sub plan for new test packages added for staging
310    plan = tools.TestPlan(packages)
311    for package, test_list in small_tests.iteritems():
312      plan.Exclude(package+'$')
313    for package, test_list in medium_tests.iteritems():
314      plan.Exclude(package+'$')
315    for package, tests_list in new_test_packages.iteritems():
316      plan.Exclude(package+'$')
317    plan.Exclude(r'com\.drawelements\.')
318    plan.Exclude(r'android\.hardware$')
319    plan.Exclude(r'android\.media$')
320    plan.Exclude(r'android\.view$')
321    plan.Exclude(r'android\.mediastress$')
322    plan.Exclude(r'android\.browser')
323    plan.Exclude('android\.car')
324    for package, test_list in flaky_tests.iteritems():
325      plan.ExcludeTests(package, test_list)
326    for package, test_list in releasekey_tests.iteritems():
327      plan.ExcludeTests(package, test_list)
328    self.__WritePlan(plan, 'CTS-m-tests')
329
330
331    # CTS - sub plan for new test packages added for staging
332    plan = tools.TestPlan(packages)
333    plan.Exclude('.*')
334    for package, test_list in temporarily_known_failure_tests.iteritems():
335      plan.Include(package+'$')
336      plan.IncludeTests(package, test_list)
337    self.__WritePlan(plan, 'CTS-staging')
338
339    plan = tools.TestPlan(packages)
340    plan.Exclude('.*')
341    self.__WritePlan(plan, 'CTS-webview')
342
343    # CTS - sub plan for Security
344    plan = tools.TestPlan(packages)
345    plan.Exclude('.*')
346    plan.Include(r'android\.security$')
347    plan.Include('android\.host\.jdwpsecurity$')
348    plan.Include('android\.host\.abioverride$')
349    self.__WritePlan(plan, 'Security')
350
351def BuildAospMediumSizeTestList():
352  """ Construct a defaultdic that lists package names of medium tests
353      already published to aosp. """
354  return {
355      'android.app' : [],
356      'android.core.tests.libcore.package.libcore' : [],
357      'android.core.tests.libcore.package.org' : [],
358      'android.core.vm-tests-tf' : [],
359      'android.dpi' : [],
360      'android.host.security' : [],
361      'android.net' : [],
362      'android.os' : [],
363      'android.permission2' : [],
364      'android.security' : [],
365      'android.telephony' : [],
366      'android.webkit' : [],
367      'android.widget' : [],
368      'android.browser' : []}
369
370def BuildAospSmallSizeTestList():
371  """ Construct a default dict that lists packages names of small tests
372      already published to aosp. """
373  return {
374      'android.aadb' : [],
375      'android.acceleration' : [],
376      'android.accessibility' : [],
377      'android.accessibilityservice' : [],
378      'android.accounts' : [],
379      'android.admin' : [],
380      'android.animation' : [],
381      'android.appsecurity' : [],
382      'android.bionic' : [],
383      'android.bluetooth' : [],
384      'android.calendarcommon' : [],
385      'android.content' : [],
386      'android.core.tests.libcore.package.com' : [],
387      'android.core.tests.libcore.package.conscrypt' : [],
388      'android.core.tests.libcore.package.dalvik' : [],
389      'android.core.tests.libcore.package.sun' : [],
390      'android.core.tests.libcore.package.tests' : [],
391      'android.database' : [],
392      'android.dram' : [],
393      'android.dreams' : [],
394      'android.drm' : [],
395      'android.effect' : [],
396      'android.filesystem' : [],
397      'android.gesture' : [],
398      'android.graphics' : [],
399      'android.graphics2' : [],
400      'android.jni' : [],
401      'android.keystore' : [],
402      'android.location' : [],
403      'android.nativemedia.sl' : [],
404      'android.nativemedia.xa' : [],
405      'android.ndef' : [],
406      'android.opengl' : [],
407      'android.openglperf' : [],
408      'android.permission' : [],
409      'android.preference' : [],
410      'android.preference2' : [],
411      'android.provider' : [],
412      'android.renderscript' : [],
413      'android.rscpp' : [],
414      'android.rsg' : [],
415      'android.sax' : [],
416      'android.server' : [],
417      'android.signature' : [],
418      'android.simplecpu' : [],
419      'android.simpleperf' : [],
420      'android.speech' : [],
421      'android.text' : [],
422      'android.textureview' : [],
423      'android.theme' : [],
424      'android.usb' : [],
425      'android.util' : [],
426      'android.video' : [],
427      'com.android.cts.jank' : [],
428      'com.android.cts.jank2' : [],
429      'com.android.cts.opengl' : [],
430      'com.android.cts.ui' : [],
431      'com.android.cts.uihost' : [],
432      'zzz.android.monkey' : []}
433
434def BuildCtsVettedNewPackagesList():
435  """ Construct a defaultdict that maps package names that is vetted for L. """
436  return {
437      'android.JobScheduler' : [],
438      'android.core.tests.libcore.package.harmony_annotation' : [],
439      'android.core.tests.libcore.package.harmony_beans' : [],
440      'android.core.tests.libcore.package.harmony_java_io' : [],
441      'android.core.tests.libcore.package.harmony_java_lang' : [],
442      'android.core.tests.libcore.package.harmony_java_math' : [],
443      'android.core.tests.libcore.package.harmony_java_net' : [],
444      'android.core.tests.libcore.package.harmony_java_nio' : [],
445      'android.core.tests.libcore.package.harmony_java_util' : [],
446      'android.core.tests.libcore.package.harmony_java_text' : [],
447      'android.core.tests.libcore.package.harmony_javax_security' : [],
448      'android.core.tests.libcore.package.harmony_logging' : [],
449      'android.core.tests.libcore.package.harmony_prefs' : [],
450      'android.core.tests.libcore.package.harmony_sql' : [],
451      'android.core.tests.libcore.package.jsr166' : [],
452      'android.core.tests.libcore.package.okhttp' : [],
453      'android.display' : [],
454      'android.host.theme' : [],
455      'android.jdwp' : [],
456      'android.location2' : [],
457      'android.print' : [],
458      'android.renderscriptlegacy' : [],
459      'android.signature' : [],
460      'android.tv' : [],
461      'android.uiautomation' : [],
462      'android.uirendering' : []}
463
464def BuildListForReleaseBuildTest():
465  """ Construct a defaultdict that maps package name to a list of tests
466      that are expected to pass only when running against a user/release-key build. """
467  return {
468      'android.app' : [
469          'android.app.cts.ActivityManagerTest#testIsRunningInTestHarness',],
470      'android.dpi' : [
471          'android.dpi.cts.DefaultManifestAttributesSdkTest#testPackageHasExpectedSdkVersion',],
472      'android.host.security' : [
473          'android.cts.security.SELinuxHostTest#testAllEnforcing',
474          'android.cts.security.SELinuxHostTest#testSuDomain',],
475      'android.os' : [
476          'android.os.cts.BuildVersionTest#testReleaseVersion',
477          'android.os.cts.BuildTest#testIsSecureUserBuild',],
478      'android.security' : [
479          'android.security.cts.BannedFilesTest#testNoSu',
480          'android.security.cts.BannedFilesTest#testNoSuInPath',
481          'android.security.cts.PackageSignatureTest#testPackageSignatures',
482          'android.security.cts.SELinuxDomainTest#testSuDomain',],
483      '' : []}
484
485def BuildCtsFlakyTestList():
486  """ Construct a defaultdict that maps package name to a list of tests
487      that flaky during dev cycle and cause other subsequent tests to fail. """
488  return {
489      'android.camera' : [
490          'android.hardware.cts.CameraTest#testVideoSnapshot',
491          'android.hardware.cts.CameraGLTest#testCameraToSurfaceTextureMetadata',
492          'android.hardware.cts.CameraGLTest#testSetPreviewTextureBothCallbacks',
493          'android.hardware.cts.CameraGLTest#testSetPreviewTexturePreviewCallback',],
494      'android.media' : [
495          'android.media.cts.DecoderTest#testCodecResetsH264WithSurface',
496          'android.media.cts.StreamingMediaPlayerTest#testHLS',],
497      'android.net' : [
498          'android.net.cts.ConnectivityManagerTest#testStartUsingNetworkFeature_enableHipri',
499          'android.net.cts.DnsTest#testDnsWorks',
500          'android.net.cts.SSLCertificateSocketFactoryTest#testCreateSocket',
501          'android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_bind',
502          'android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_simple',
503          'android.net.cts.SSLCertificateSocketFactoryTest#test_createSocket_wrapping',
504          'android.net.cts.TrafficStatsTest#testTrafficStatsForLocalhost',
505          'android.net.wifi.cts.NsdManagerTest#testAndroidTestCaseSetupProperly',],
506      'android.security' : [
507          'android.security.cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdp6Ports',
508          'android.security.cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdpPorts',],
509      'android.webkit' : [
510          'android.webkit.cts.WebViewClientTest#testOnUnhandledKeyEvent',],
511      'com.android.cts.filesystemperf' : [
512          'com.android.cts.filesystemperf.RandomRWTest#testRandomRead',
513          'com.android.cts.filesystemperf.RandomRWTest#testRandomUpdate',],
514      '' : []}
515
516def BuildCtsTemporarilyKnownFailureList():
517  """ Construct a defaultdict that maps package name to a list of tests
518      that are known failures during dev cycle but expected to be fixed before launch """
519  return {
520      'android.alarmclock' : [
521          'android.alarmclock.cts.DismissAlarmTest#testAll',
522          'android.alarmclock.cts.SetAlarmTest#testAll',
523          'android.alarmclock.cts.SnoozeAlarmTest#testAll',
524      ],
525      'android.dumpsys' : [
526          'android.dumpsys.cts.DumpsysHostTest#testBatterystatsOutput',
527          'android.dumpsys.cts.DumpsysHostTest#testGfxinfoFramestats',
528      ],
529      'android.telecom' : [
530          'android.telecom.cts.ExtendedInCallServiceTest#testAddNewOutgoingCallAndThenDisconnect',
531          'android.telecom.cts.RemoteConferenceTest#testRemoteConferenceCallbacks_ConferenceableConnections',
532      ],
533      'android.transition' : [
534          'android.transition.cts.ChangeScrollTest#testChangeScroll',
535      ],
536      'android.voicesettings' : [
537          'android.voicesettings.cts.ZenModeTest#testAll',
538      ],
539      'android.systemui.cts' : [
540          'android.systemui.cts.LightStatusBarTests#testLightStatusBarIcons',
541      ],
542      'com.android.cts.app.os' : [
543          'com.android.cts.app.os.OsHostTests#testNonExportedActivities',
544      ],
545      'com.android.cts.devicepolicy' : [
546          'com.android.cts.devicepolicy.MixedDeviceOwnerTest#testPackageInstallUserRestrictions',
547          'com.android.cts.devicepolicy.MixedProfileOwnerTest#testPackageInstallUserRestrictions',
548      ],
549      '' : []}
550
551def BuildCtsMiscCameraList():
552  """ Construct a defaultdict that maps package name to a list of tests
553      that are relevant to camera but does not reside in camera test package """
554  return {
555      'android.app' : [
556          'android.app.cts.SystemFeaturesTest#testCameraFeatures',
557      ],
558      'android.permission' : [
559          'android.permission.cts.CameraPermissionTest',
560          'android.permission.cts.Camera2PermissionTest',
561      ],
562      '' : []}
563
564def LogGenerateDescription(name):
565  print 'Generating test description for package %s' % name
566
567if __name__ == '__main__':
568  builder = CtsBuilder(sys.argv)
569  result = builder.GenerateTestDescriptions()
570  if result != 0:
571    sys.exit(result)
572  builder.GenerateTestPlans()
573