Home | History | Annotate | Download | only in script
      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2016 - 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 
     18 # Initiate a test case directory.
     19 # This script copy a template which contains Android.mk, __init__.py files,
     20 # AndroidTest.xml and a test case python file into a given relative directory
     21 # under testcases/ using the given test name.
     22 
     23 import os
     24 import sys
     25 import datetime
     26 import re
     27 import shutil
     28 import argparse
     29 
     30 VTS_PATH = 'test/vts'
     31 VTS_TEST_CASE_PATH = os.path.join(VTS_PATH, 'testcases')
     32 PYTHON_INIT_FILE_NAME = '__init__.py'
     33 ANDROID_MK_FILE_NAME = 'Android.mk'
     34 ANDROID_TEST_XML_FILE_NAME = 'AndroidTest.xml'
     35 
     36 
     37 class TestCaseCreator(object):
     38     '''Init a test case directory with helloworld test case.
     39 
     40     Attributes:
     41         test_name: string, test case name in UpperCamel
     42         build_top: string, equal to environment variable ANDROID_BUILD_TOP
     43         test_dir: string, test case absolute directory
     44         test_name: string, test case name in UpperCamel
     45         test_type: test type, such as HidlHalTest, HostDrivenTest, etc
     46         current_year: current year
     47         vts_test_case_dir: absolute dir of vts testcases directory
     48     '''
     49 
     50     def __init__(self, test_name, test_dir_under_testcases, test_type):
     51         '''Initialize class attributes.
     52 
     53         Args:
     54             test_name: string, test case name in UpperCamel
     55             test_dir_under_testcases: string, test case relative directory under
     56                                       test/vts/testcases.
     57         '''
     58         if not test_dir_under_testcases:
     59             print 'Error: Empty test directory entered. Exiting'
     60             sys.exit(3)
     61         test_dir_under_testcases = os.path.normpath(
     62             test_dir_under_testcases.strip())
     63 
     64         if not self.IsUpperCamel(test_name):
     65             print 'Error: Test name not in UpperCamel case. Exiting'
     66             sys.exit(4)
     67         self.test_name = test_name
     68 
     69         if not test_type:
     70             self.test_type = 'HidlHalTest'
     71         else:
     72             self.test_type = test_type
     73 
     74         self.build_top = os.getenv('ANDROID_BUILD_TOP')
     75         if not self.build_top:
     76             print('Error: Missing ANDROID_BUILD_TOP env variable. Please run '
     77                   '\'. build/envsetup.sh; lunch <build target>\' Exiting...')
     78             sys.exit(1)
     79 
     80         self.vts_test_case_dir = os.path.abspath(
     81             os.path.join(self.build_top, VTS_TEST_CASE_PATH))
     82 
     83         self.test_dir = os.path.abspath(
     84             os.path.join(self.vts_test_case_dir, test_dir_under_testcases))
     85 
     86         self.current_year = datetime.datetime.now().year
     87 
     88     def InitTestCaseDir(self):
     89         '''Start init test case directory'''
     90         if os.path.exists(self.test_dir):
     91             print 'Error: Test directory already exists. Exiting...'
     92             sys.exit(2)
     93         try:
     94             os.makedirs(self.test_dir)
     95         except:
     96             print('Error: Failed to create test directory at %s. '
     97                   'Exiting...' % self.test_dir)
     98             sys.exit(2)
     99 
    100         self.CreatePythonInitFile()
    101         self.CreateAndroidMk()
    102         self.CreateAndroidTestXml()
    103         self.CreateTestCasePy()
    104 
    105     def UpperCamelToLowerUnderScore(self, name):
    106         '''Convert UpperCamel name to lower_under_score name.
    107 
    108         Args:
    109             name: string in UpperCamel.
    110 
    111         Returns:
    112             a lower_under_score version of the given name
    113         '''
    114         return re.sub('(?!^)([A-Z]+)', r'_\1', name).lower()
    115 
    116     def IsUpperCamel(self, name):
    117         '''Check whether a given name is UpperCamel case.
    118 
    119         Args:
    120             name: string.
    121 
    122         Returns:
    123             True if name is in UpperCamel case, False otherwise
    124         '''
    125         regex = re.compile('((?:[A-Z][a-z]+)[0-9]*)+')
    126         match = regex.match(name)
    127         return match and (match.end() - match.start() == len(name))
    128 
    129     def CreatePythonInitFile(self):
    130         '''Populate test case directory and parent directories with __init__.py.
    131         '''
    132         if not self.test_dir.startswith(self.vts_test_case_dir):
    133             print 'Error: Test case directory is not under VTS test case directory.'
    134             sys.exit(4)
    135 
    136         path = self.test_dir
    137         while not path == self.vts_test_case_dir:
    138             target = os.path.join(path, PYTHON_INIT_FILE_NAME)
    139             if not os.path.exists(target):
    140                 print 'Creating %s' % target
    141                 with open(target, 'w') as f:
    142                     pass
    143             path = os.path.dirname(path)
    144 
    145     def CreateAndroidMk(self):
    146         '''Populate test case directory and parent directories with Android.mk
    147         '''
    148         vts_dir = os.path.join(self.build_top, VTS_PATH)
    149 
    150         target = os.path.join(self.test_dir, ANDROID_MK_FILE_NAME)
    151         with open(target, 'w') as f:
    152             print 'Creating %s' % target
    153             f.write(LICENSE_STATEMENT_POUND.format(year=self.current_year))
    154             f.write('\n')
    155             f.write(
    156                 ANDROID_MK_TEMPLATE.format(
    157                     test_name=self.test_name,
    158                     config_src_dir=self.test_dir[len(vts_dir) + 1:]))
    159 
    160         path = self.test_dir
    161         while not path == vts_dir:
    162             target = os.path.join(path, ANDROID_MK_FILE_NAME)
    163             if not os.path.exists(target):
    164                 print 'Creating %s' % target
    165                 with open(target, 'w') as f:
    166                     f.write(
    167                         LICENSE_STATEMENT_POUND.format(year=self.current_year))
    168                     f.write(ANDROID_MK_CALL_SUB)
    169             path = os.path.dirname(path)
    170 
    171     def CreateAndroidTestXml(self):
    172         '''Create AndroidTest.xml'''
    173         target = os.path.join(self.test_dir, ANDROID_TEST_XML_FILE_NAME)
    174         with open(target, 'w') as f:
    175             print 'Creating %s' % target
    176             f.write(XML_HEADER)
    177             f.write(LICENSE_STATEMENT_XML.format(year=self.current_year))
    178             f.write(
    179                 ANDROID_TEST_XML_TEMPLATE.format(
    180                     test_name=self.test_name,
    181                     test_type=self.test_type,
    182                     test_path_under_vts=self.test_dir[
    183                         len(os.path.join(self.build_top, VTS_PATH)) + 1:],
    184                     test_case_file_without_extension=self.test_name))
    185 
    186     def CreateTestCasePy(self):
    187         '''Create <test_case_name>.py'''
    188         target = os.path.join(self.test_dir, '%s.py' % self.test_name)
    189         with open(target, 'w') as f:
    190             print 'Creating %s' % target
    191             f.write(PY_HEADER)
    192             f.write(LICENSE_STATEMENT_POUND.format(year=self.current_year))
    193             f.write('\n')
    194             f.write(TEST_CASE_PY_TEMPLATE.format(test_name=self.test_name))
    195 
    196 
    197 def main():
    198     parser = argparse.ArgumentParser(description='Initiate a test case.')
    199     parser.add_argument(
    200         '--name',
    201         dest='test_name',
    202         required=True,
    203         help='Test case name in UpperCamel. Example: VtsKernelLtp')
    204     parser.add_argument(
    205         '--dir',
    206         dest='test_dir',
    207         required=True,
    208         help='Test case relative directory under test/vts/testcses.')
    209     parser.add_argument(
    210         '--type',
    211         dest='test_type',
    212         required=False,
    213         help='Test type, such as HidlHalTest, HostDrivenTest, etc.')
    214 
    215     args = parser.parse_args()
    216     test_case_creater = TestCaseCreator(args.test_name, args.test_dir,
    217                                         args.test_type)
    218     test_case_creater.InitTestCaseDir()
    219 
    220 
    221 LICENSE_STATEMENT_POUND = '''#
    222 # Copyright (C) {year} The Android Open Source Project
    223 #
    224 # Licensed under the Apache License, Version 2.0 (the "License");
    225 # you may not use this file except in compliance with the License.
    226 # You may obtain a copy of the License at
    227 #
    228 #      http://www.apache.org/licenses/LICENSE-2.0
    229 #
    230 # Unless required by applicable law or agreed to in writing, software
    231 # distributed under the License is distributed on an "AS IS" BASIS,
    232 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    233 # See the License for the specific language governing permissions and
    234 # limitations under the License.
    235 #
    236 '''
    237 
    238 LICENSE_STATEMENT_XML = '''<!-- Copyright (C) {year} The Android Open Source Project
    239 
    240      Licensed under the Apache License, Version 2.0 (the "License");
    241      you may not use this file except in compliance with the License.
    242      You may obtain a copy of the License at
    243 
    244           http://www.apache.org/licenses/LICENSE-2.0
    245 
    246      Unless required by applicable law or agreed to in writing, software
    247      distributed under the License is distributed on an "AS IS" BASIS,
    248      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    249      See the License for the specific language governing permissions and
    250      limitations under the License.
    251 -->
    252 '''
    253 
    254 ANDROID_MK_TEMPLATE = '''LOCAL_PATH := $(call my-dir)
    255 
    256 include $(call all-subdir-makefiles)
    257 
    258 include $(CLEAR_VARS)
    259 
    260 LOCAL_MODULE := {test_name}
    261 VTS_CONFIG_SRC_DIR := {config_src_dir}
    262 include test/vts/tools/build/Android.host_config.mk
    263 '''
    264 
    265 ANDROID_MK_CALL_SUB = '''LOCAL_PATH := $(call my-dir)
    266 
    267 include $(call all-subdir-makefiles)
    268 '''
    269 
    270 XML_HEADER = '''<?xml version="1.0" encoding="utf-8"?>
    271 '''
    272 
    273 ANDROID_TEST_XML_TEMPLATE = '''<configuration description="Config for VTS {test_name} test cases">
    274     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
    275         <option name="push-group" value="{test_type}.push" />
    276     </target_preparer>
    277     <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
    278     </target_preparer>
    279     <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
    280         <option name="test-module-name" value="{test_name}" />
    281         <option name="test-case-path" value="vts/{test_path_under_vts}/{test_case_file_without_extension}" />
    282     </test>
    283 </configuration>
    284 '''
    285 
    286 PY_HEADER = '''#!/usr/bin/env python
    287 '''
    288 
    289 TEST_CASE_PY_TEMPLATE = '''import logging
    290 
    291 from vts.runners.host import asserts
    292 from vts.runners.host import base_test
    293 from vts.runners.host import const
    294 from vts.runners.host import test_runner
    295 
    296 
    297 
    298 class {test_name}(base_test.BaseTestClass):
    299     """Two hello world test cases which use the shell driver."""
    300 
    301     def setUpClass(self):
    302         self.dut = self.android_devices[0]
    303         self.shell = self.dut.shell
    304 
    305     def testEcho1(self):
    306         """A simple testcase which sends a command."""
    307         results = self.shell.Execute("echo hello_world")  # runs a shell command.
    308         logging.info(str(results[const.STDOUT]))  # prints the stdout
    309         asserts.assertEqual(results[const.STDOUT][0].strip(), "hello_world")  # checks the stdout
    310         asserts.assertEqual(results[const.EXIT_CODE][0], 0)  # checks the exit code
    311 
    312     def testEcho2(self):
    313         """A simple testcase which sends two commands."""
    314         results = self.shell.Execute(["echo hello", "echo world"])
    315         logging.info(str(results[const.STDOUT]))
    316         asserts.assertEqual(len(results[const.STDOUT]), 2)  # check the number of processed commands
    317         asserts.assertEqual(results[const.STDOUT][0].strip(), "hello")
    318         asserts.assertEqual(results[const.STDOUT][1].strip(), "world")
    319         asserts.assertEqual(results[const.EXIT_CODE][0], 0)
    320         asserts.assertEqual(results[const.EXIT_CODE][1], 0)
    321 
    322 
    323 if __name__ == "__main__":
    324     test_runner.main()
    325 '''
    326 
    327 if __name__ == '__main__':
    328     main()
    329