130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma#!/usr/bin/env python 230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# 330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# Copyright 2016 - The Android Open Source Project 430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# 530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# Licensed under the Apache License, Version 2.0 (the "License"); 630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# you may not use this file except in compliance with the License. 730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# You may obtain a copy of the License at 830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# 930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# http://www.apache.org/licenses/LICENSE-2.0 1030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# 1130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# Unless required by applicable law or agreed to in writing, software 1230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# distributed under the License is distributed on an "AS IS" BASIS, 1330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# See the License for the specific language governing permissions and 1530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# limitations under the License. 1630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma# 1730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 1830b765ffef37427ca3715389a2a057c875f56e4aYuexi Maimport os 1930b765ffef37427ca3715389a2a057c875f56e4aYuexi Maimport argparse 2030b765ffef37427ca3715389a2a057c875f56e4aYuexi Maimport math 2130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 227086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma 2330b765ffef37427ca3715389a2a057c875f56e4aYuexi Maclass Module(object): 2430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """class used to represent a ltp module 2530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 2630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Attribute: 2730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _lines: list of string, lines of module text 2830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _header: list of string, first line of module splited by := 2930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _type: string, type of module 3030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _path: string, path of module 3130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _output_dir: string, output directory of module 3230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 3330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _lines = None 3430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _header = None 3530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _type = None 3630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _path = None 3730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _output_dir = None 3830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 3930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def __init__(self, output_dir): 4030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._output_dir = output_dir 4130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 4230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def parse(self, module_text): 4330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """parse a module text 4430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 4530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Args: 4630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma module_text: string, one block of ltp module build rule. 4730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma output_dir: string, ltp compile output directory 4830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 4930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Return: 5030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma None if the input text is not a ltp module 5130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Self if parsed succesfully 5230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 5330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._lines = module_text.splitlines() 5430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma if len(self._lines) < 2: 5530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._type = None 5630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return None 5730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._header = self._lines[0].split(' := ') 5830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma if len(self._header) < 2: 5930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._type = None 6030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return None 6130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._type = self._header[0] 6230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._path = self._header[1] 6330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return self 6430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 6530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def IsBuildSuccess(self, counts): 6630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """Check whether a given module specified in Android.mk file 6730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma is succesfully built 6830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 6930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Returns: 7030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma True if success 7130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 7230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma if self._type is None: 7330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return False 7430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 7530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma counts[self._type] = counts.get(self._type, 0) + 1 7630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 777086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma success = {"module_testname": self.IsBuildSuccessModuleTestname, 787086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma "module_libname": self.IsBuildSuccessModuleLibname, 797086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma "module_prebuilt": self.IsBuildSuccessModulePrebuilt, 807086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma }[self._type]() 8130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 8230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma if not success: 8330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma print " Module build failed: " + os.path.basename(self._path) 8430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return success 8530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 8630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def IsBuildSuccessModuleTestname(self): 8730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """Check whether a given ltp test module in Android.mk file 8830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma is succesfully built 8930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 9030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Args: 9130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma module_path: string, the path of module on the first 9230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma line of the block 9330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 9430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Returns: 9530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma True if success 9630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 9730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 9830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return os.path.isfile(self._output_dir + \ 9930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma "testcases/bin/" + \ 10030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma os.path.basename(self._path)) 10130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 10230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def IsBuildSuccessModuleLibname(self): 10330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """Check whether a given ltp lib module in Android.mk file 10430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma is succesfully built 10530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 10630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Args: 10730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma module_path: the path of module on the first line of 10830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma the block 10930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 11030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Returns: 11130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma True if success 11230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 11330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma # TODO(yuexima) check lib build 11430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma print "Checking module_lib is not supported now, " + \ 11530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma "assuming build success: " + self._path 11630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return True 11730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 11830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def IsBuildSuccessModulePrebuilt(self): 11930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """Check whether a given prebuilt module in Android.mk file 12030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma is succesfully built 12130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 12230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Args: 12330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma module_path: string, the path of module on the first 12430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma line of the block 12530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 12630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Returns: 12730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma True if success 12830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 12930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return os.path.isfile(self._output_dir + self._path) 13030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 13130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 13230b765ffef37427ca3715389a2a057c875f56e4aYuexi Maclass LtpModuleChecker(object): 13330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """LTP module result check class. 13430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Checks for success build of each module in LTP's Android.mk file 13530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma and rewrite it with only successfully built modules. 13630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 13730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _output_dir = "" 13830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _file_path_android_ltp_mk = "" 13930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma _module_counts = {} 14030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 14130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def __init__(self, android_build_top, ltp_dir, target_product): 14230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._output_dir = android_build_top + '/out/target/product/' + \ 14330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma target_product + '/data/nativetest/ltp/' 14430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma self._file_path_android_ltp_mk = ltp_dir + '/Android.ltp.mk' 14530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 14630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def Read(self, file_path): 14730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """Read a file and return its entire content 14830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 14930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Args: 15030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma file_path: string, file path 15130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 15230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma Returns: 15330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma entire file content in string format 15430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 15530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma with open(file_path, 'r') as file: 15630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma return file.read() 15730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 15830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def LoadModules(self): 15930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """Read the LTP Android.mk file and seperate modules into 16030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma a list of string 16130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """ 1627086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma return self.Read(self._file_path_android_ltp_mk).split("\n\n") 16330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 16430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma def CheckModules(self): 16530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma """Start the LTP module build result checking and counting.""" 16630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma modules = [Module(self._output_dir).parse(module) 1677086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma for module in self.LoadModules()] 16830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma modules_succeed = \ 16930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma [module for module in modules 17030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma if module is not None and 17130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma module.IsBuildSuccess(self._module_counts) 17230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma ] 17330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 17430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma print "module type counts:" 17530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma print self._module_counts 17630b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 17730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma print str(len(modules_succeed)) + \ 17830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma " of " + str(sum([self._module_counts[i] 17930b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma for i in self._module_counts])) + \ 18030b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma " modules were succesfully built." 18130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma print "--Check complete." 18230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 18330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 18430b765ffef37427ca3715389a2a057c875f56e4aYuexi Madef main(): 18530b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma parser = argparse.ArgumentParser( 1867086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma description='Generate Android.mk from parsed LTP make output') 1877086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma parser.add_argument( 1887086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma '--android_build_top', 1897086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma dest='android_build_top', 1907086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma required=True, 1917086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma help='android build top directory') 1927086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma parser.add_argument( 1937086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma '--ltp_dir', 1947086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma dest='ltp_dir', 1957086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma required=True, 1967086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma help='directory for the forked ltp project') 1977086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma parser.add_argument( 1987086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma '--target_product', 1997086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma dest='target_product', 2007086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma required=True, 2017086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma help='target product name, \ 20230b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma such as "bullhead", "angler", etc.') 20330b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma args = parser.parse_args() 20430b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 2057086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma checker = LtpModuleChecker(args.android_build_top, args.ltp_dir, 2067086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma args.target_product) 20730b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma checker.CheckModules() 20830b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma 2097086b40fbaf278f8af6d37ce55e196ea8c654d27Yuexi Ma 21030b765ffef37427ca3715389a2a057c875f56e4aYuexi Maif __name__ == '__main__': 21130b765ffef37427ca3715389a2a057c875f56e4aYuexi Ma main() 212