#!/usr/bin/env python # # Copyright 2016 - The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Initiate a test case directory. # This script copy a template which contains Android.mk, __init__.py files, # AndroidTest.xml and a test case python file into a given relative directory # under testcases/ using the given test name. import os import sys import datetime import re import shutil import argparse VTS_PATH = 'test/vts' VTS_TEST_CASE_PATH = os.path.join(VTS_PATH, 'testcases') PYTHON_INIT_FILE_NAME = '__init__.py' ANDROID_MK_FILE_NAME = 'Android.mk' ANDROID_TEST_XML_FILE_NAME = 'AndroidTest.xml' class TestCaseCreator(object): '''Init a test case directory with helloworld test case. Attributes: test_name: string, test case name in UpperCamel build_top: string, equal to environment variable ANDROID_BUILD_TOP test_dir: string, test case absolute directory test_name: string, test case name in UpperCamel test_plan: string, the plan that the test belongs to test_type: test type, such as HidlHalTest, HostDrivenTest, etc current_year: current year vts_test_case_dir: absolute dir of vts testcases directory ''' def __init__(self, test_name, test_plan, test_dir_under_testcases, test_type): '''Initialize class attributes. Args: test_name: string, test case name in UpperCamel test_plan: string, the plan that the test belongs to test_dir_under_testcases: string, test case relative directory under test/vts/testcases. ''' if not test_dir_under_testcases: print 'Error: Empty test directory entered. Exiting' sys.exit(3) test_dir_under_testcases = os.path.normpath( test_dir_under_testcases.strip()) if not self.IsUpperCamel(test_name): print 'Error: Test name not in UpperCamel case. Exiting' sys.exit(4) self.test_name = test_name if not test_plan: self.test_plan = 'vts-misc' else: self.test_plan = test_plan if not test_type: self.test_type = 'HidlHalTest' else: self.test_type = test_type self.build_top = os.getenv('ANDROID_BUILD_TOP') if not self.build_top: print('Error: Missing ANDROID_BUILD_TOP env variable. Please run ' '\'. build/envsetup.sh; lunch \' Exiting...') sys.exit(1) self.vts_test_case_dir = os.path.abspath( os.path.join(self.build_top, VTS_TEST_CASE_PATH)) self.test_dir = os.path.abspath( os.path.join(self.vts_test_case_dir, test_dir_under_testcases)) self.current_year = datetime.datetime.now().year def InitTestCaseDir(self): '''Start init test case directory''' if os.path.exists(self.test_dir): print 'Error: Test directory already exists. Exiting...' sys.exit(2) try: os.makedirs(self.test_dir) except: print('Error: Failed to create test directory at %s. ' 'Exiting...' % self.test_dir) sys.exit(2) self.CreatePythonInitFile() self.CreateAndroidMk() self.CreateAndroidTestXml() self.CreateTestCasePy() def UpperCamelToLowerUnderScore(self, name): '''Convert UpperCamel name to lower_under_score name. Args: name: string in UpperCamel. Returns: a lower_under_score version of the given name ''' return re.sub('(?!^)([A-Z]+)', r'_\1', name).lower() def IsUpperCamel(self, name): '''Check whether a given name is UpperCamel case. Args: name: string. Returns: True if name is in UpperCamel case, False otherwise ''' regex = re.compile('((?:[A-Z][a-z]+)[0-9]*)+') match = regex.match(name) return match and (match.end() - match.start() == len(name)) def CreatePythonInitFile(self): '''Populate test case directory and parent directories with __init__.py. ''' if not self.test_dir.startswith(self.vts_test_case_dir): print 'Error: Test case directory is not under VTS test case directory.' sys.exit(4) path = self.test_dir while not path == self.vts_test_case_dir: target = os.path.join(path, PYTHON_INIT_FILE_NAME) if not os.path.exists(target): print 'Creating %s' % target with open(target, 'w') as f: pass path = os.path.dirname(path) def CreateAndroidMk(self): '''Populate test case directory and parent directories with Android.mk ''' vts_dir = os.path.join(self.build_top, VTS_PATH) target = os.path.join(self.test_dir, ANDROID_MK_FILE_NAME) with open(target, 'w') as f: print 'Creating %s' % target f.write(LICENSE_STATEMENT_POUND.format(year=self.current_year)) f.write('\n') f.write( ANDROID_MK_TEMPLATE.format( test_name=self.test_name, config_src_dir=self.test_dir[len(vts_dir) + 1:])) path = self.test_dir while not path == vts_dir: target = os.path.join(path, ANDROID_MK_FILE_NAME) if not os.path.exists(target): print 'Creating %s' % target with open(target, 'w') as f: f.write( LICENSE_STATEMENT_POUND.format(year=self.current_year)) f.write(ANDROID_MK_CALL_SUB) path = os.path.dirname(path) def CreateAndroidTestXml(self): '''Create AndroidTest.xml''' target = os.path.join(self.test_dir, ANDROID_TEST_XML_FILE_NAME) with open(target, 'w') as f: print 'Creating %s' % target f.write(XML_HEADER) f.write(LICENSE_STATEMENT_XML.format(year=self.current_year)) f.write( ANDROID_TEST_XML_TEMPLATE.format( test_name=self.test_name, test_plan=self.test_plan, test_type=self.test_type, test_path_under_vts=self.test_dir[ len(os.path.join(self.build_top, VTS_PATH)) + 1:], test_case_file_without_extension=self.test_name)) def CreateTestCasePy(self): '''Create .py''' target = os.path.join(self.test_dir, '%s.py' % self.test_name) with open(target, 'w') as f: print 'Creating %s' % target f.write(PY_HEADER) f.write(LICENSE_STATEMENT_POUND.format(year=self.current_year)) f.write('\n') f.write(TEST_CASE_PY_TEMPLATE.format(test_name=self.test_name)) def main(): parser = argparse.ArgumentParser(description='Initiate a test case.') parser.add_argument( '--name', dest='test_name', required=True, help='Test case name in UpperCamel. Example: VtsKernelLtp') parser.add_argument( '--plan', dest='test_plan', required=False, help='The plan that the test belongs to. Example: vts-kernel') parser.add_argument( '--dir', dest='test_dir', required=True, help='Test case relative directory under test/vts/testcses.') parser.add_argument( '--type', dest='test_type', required=False, help='Test type, such as HidlHalTest, HostDrivenTest, etc.') args = parser.parse_args() test_case_creater = TestCaseCreator(args.test_name, args.test_plan, args.test_dir, args.test_type) test_case_creater.InitTestCaseDir() LICENSE_STATEMENT_POUND = '''# # Copyright (C) {year} The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ''' LICENSE_STATEMENT_XML = ''' ''' ANDROID_MK_TEMPLATE = '''LOCAL_PATH := $(call my-dir) include $(call all-subdir-makefiles) include $(CLEAR_VARS) LOCAL_MODULE := {test_name} include test/vts/tools/build/Android.host_config.mk ''' ANDROID_MK_CALL_SUB = '''LOCAL_PATH := $(call my-dir) include $(call all-subdir-makefiles) ''' XML_HEADER = ''' ''' ANDROID_TEST_XML_TEMPLATE = ''' ''' PY_HEADER = '''#!/usr/bin/env python ''' TEST_CASE_PY_TEMPLATE = '''import logging from vts.runners.host import asserts from vts.runners.host import base_test from vts.runners.host import const from vts.runners.host import test_runner class {test_name}(base_test.BaseTestClass): """Two hello world test cases which use the shell driver.""" def setUpClass(self): self.dut = self.android_devices[0] self.shell = self.dut.shell def testEcho1(self): """A simple testcase which sends a command.""" results = self.shell.Execute("echo hello_world") # runs a shell command. logging.info(str(results[const.STDOUT])) # prints the stdout asserts.assertEqual(results[const.STDOUT][0].strip(), "hello_world") # checks the stdout asserts.assertEqual(results[const.EXIT_CODE][0], 0) # checks the exit code def testEcho2(self): """A simple testcase which sends two commands.""" results = self.shell.Execute(["echo hello", "echo world"]) logging.info(str(results[const.STDOUT])) asserts.assertEqual(len(results[const.STDOUT]), 2) # check the number of processed commands asserts.assertEqual(results[const.STDOUT][0].strip(), "hello") asserts.assertEqual(results[const.STDOUT][1].strip(), "world") asserts.assertEqual(results[const.EXIT_CODE][0], 0) asserts.assertEqual(results[const.EXIT_CODE][1], 0) if __name__ == "__main__": test_runner.main() ''' if __name__ == '__main__': main()