xref: /aosp_15_r20/external/ltp/android/tools/check_success_build.py (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker#!/usr/bin/env python
2*49cdfc7eSAndroid Build Coastguard Worker#
3*49cdfc7eSAndroid Build Coastguard Worker# Copyright 2016 - The Android Open Source Project
4*49cdfc7eSAndroid Build Coastguard Worker#
5*49cdfc7eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*49cdfc7eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*49cdfc7eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*49cdfc7eSAndroid Build Coastguard Worker#
9*49cdfc7eSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
10*49cdfc7eSAndroid Build Coastguard Worker#
11*49cdfc7eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*49cdfc7eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*49cdfc7eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*49cdfc7eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*49cdfc7eSAndroid Build Coastguard Worker# limitations under the License.
16*49cdfc7eSAndroid Build Coastguard Worker#
17*49cdfc7eSAndroid Build Coastguard Worker
18*49cdfc7eSAndroid Build Coastguard Workerimport os
19*49cdfc7eSAndroid Build Coastguard Workerimport argparse
20*49cdfc7eSAndroid Build Coastguard Workerimport math
21*49cdfc7eSAndroid Build Coastguard Worker
22*49cdfc7eSAndroid Build Coastguard Worker
23*49cdfc7eSAndroid Build Coastguard Workerclass Module(object):
24*49cdfc7eSAndroid Build Coastguard Worker    """class used to represent a ltp module
25*49cdfc7eSAndroid Build Coastguard Worker
26*49cdfc7eSAndroid Build Coastguard Worker    Attribute:
27*49cdfc7eSAndroid Build Coastguard Worker       _lines: list of string, lines of module text
28*49cdfc7eSAndroid Build Coastguard Worker       _header: list of string, first line of module splited by :=
29*49cdfc7eSAndroid Build Coastguard Worker       _type: string, type of module
30*49cdfc7eSAndroid Build Coastguard Worker       _path: string, path of module
31*49cdfc7eSAndroid Build Coastguard Worker       _output_dir: string, output directory of module
32*49cdfc7eSAndroid Build Coastguard Worker    """
33*49cdfc7eSAndroid Build Coastguard Worker    _lines = None
34*49cdfc7eSAndroid Build Coastguard Worker    _header = None
35*49cdfc7eSAndroid Build Coastguard Worker    _type = None
36*49cdfc7eSAndroid Build Coastguard Worker    _path = None
37*49cdfc7eSAndroid Build Coastguard Worker    _output_dir = None
38*49cdfc7eSAndroid Build Coastguard Worker
39*49cdfc7eSAndroid Build Coastguard Worker    def __init__(self, output_dir):
40*49cdfc7eSAndroid Build Coastguard Worker        self._output_dir = output_dir
41*49cdfc7eSAndroid Build Coastguard Worker
42*49cdfc7eSAndroid Build Coastguard Worker    def parse(self, module_text):
43*49cdfc7eSAndroid Build Coastguard Worker        """parse a module text
44*49cdfc7eSAndroid Build Coastguard Worker
45*49cdfc7eSAndroid Build Coastguard Worker        Args:
46*49cdfc7eSAndroid Build Coastguard Worker           module_text: string, one block of ltp module build rule.
47*49cdfc7eSAndroid Build Coastguard Worker           output_dir: string, ltp compile output directory
48*49cdfc7eSAndroid Build Coastguard Worker
49*49cdfc7eSAndroid Build Coastguard Worker        Return:
50*49cdfc7eSAndroid Build Coastguard Worker           None if the input text is not a ltp module
51*49cdfc7eSAndroid Build Coastguard Worker           Self if parsed succesfully
52*49cdfc7eSAndroid Build Coastguard Worker        """
53*49cdfc7eSAndroid Build Coastguard Worker        self._lines = module_text.splitlines()
54*49cdfc7eSAndroid Build Coastguard Worker        if len(self._lines) < 2:
55*49cdfc7eSAndroid Build Coastguard Worker            self._type = None
56*49cdfc7eSAndroid Build Coastguard Worker            return None
57*49cdfc7eSAndroid Build Coastguard Worker        self._header = self._lines[0].split(' := ')
58*49cdfc7eSAndroid Build Coastguard Worker        if len(self._header) < 2:
59*49cdfc7eSAndroid Build Coastguard Worker            self._type = None
60*49cdfc7eSAndroid Build Coastguard Worker            return None
61*49cdfc7eSAndroid Build Coastguard Worker        self._type = self._header[0]
62*49cdfc7eSAndroid Build Coastguard Worker        self._path = self._header[1]
63*49cdfc7eSAndroid Build Coastguard Worker        return self
64*49cdfc7eSAndroid Build Coastguard Worker
65*49cdfc7eSAndroid Build Coastguard Worker    def IsBuildSuccess(self, counts):
66*49cdfc7eSAndroid Build Coastguard Worker        """Check whether a given module specified in Android.mk file
67*49cdfc7eSAndroid Build Coastguard Worker           is succesfully built
68*49cdfc7eSAndroid Build Coastguard Worker
69*49cdfc7eSAndroid Build Coastguard Worker           Returns:
70*49cdfc7eSAndroid Build Coastguard Worker               True if success
71*49cdfc7eSAndroid Build Coastguard Worker        """
72*49cdfc7eSAndroid Build Coastguard Worker        if self._type is None:
73*49cdfc7eSAndroid Build Coastguard Worker            return False
74*49cdfc7eSAndroid Build Coastguard Worker
75*49cdfc7eSAndroid Build Coastguard Worker        counts[self._type] = counts.get(self._type, 0) + 1
76*49cdfc7eSAndroid Build Coastguard Worker
77*49cdfc7eSAndroid Build Coastguard Worker        success = {"module_testname": self.IsBuildSuccessModuleTestname,
78*49cdfc7eSAndroid Build Coastguard Worker                   "module_libname": self.IsBuildSuccessModuleLibname,
79*49cdfc7eSAndroid Build Coastguard Worker                   "module_prebuilt": self.IsBuildSuccessModulePrebuilt,
80*49cdfc7eSAndroid Build Coastguard Worker                   }[self._type]()
81*49cdfc7eSAndroid Build Coastguard Worker
82*49cdfc7eSAndroid Build Coastguard Worker        if not success:
83*49cdfc7eSAndroid Build Coastguard Worker            print("  Module build failed: " + os.path.basename(self._path))
84*49cdfc7eSAndroid Build Coastguard Worker        return success
85*49cdfc7eSAndroid Build Coastguard Worker
86*49cdfc7eSAndroid Build Coastguard Worker    def IsBuildSuccessModuleTestname(self):
87*49cdfc7eSAndroid Build Coastguard Worker        """Check whether a given ltp test module in Android.mk file
88*49cdfc7eSAndroid Build Coastguard Worker           is succesfully built
89*49cdfc7eSAndroid Build Coastguard Worker
90*49cdfc7eSAndroid Build Coastguard Worker           Args:
91*49cdfc7eSAndroid Build Coastguard Worker               module_path: string, the path of module on the first
92*49cdfc7eSAndroid Build Coastguard Worker                            line of the block
93*49cdfc7eSAndroid Build Coastguard Worker
94*49cdfc7eSAndroid Build Coastguard Worker           Returns:
95*49cdfc7eSAndroid Build Coastguard Worker               True if success
96*49cdfc7eSAndroid Build Coastguard Worker        """
97*49cdfc7eSAndroid Build Coastguard Worker
98*49cdfc7eSAndroid Build Coastguard Worker        return os.path.isfile(self._output_dir + \
99*49cdfc7eSAndroid Build Coastguard Worker                              "testcases/bin/" + \
100*49cdfc7eSAndroid Build Coastguard Worker                              os.path.basename(self._path))
101*49cdfc7eSAndroid Build Coastguard Worker
102*49cdfc7eSAndroid Build Coastguard Worker    def IsBuildSuccessModuleLibname(self):
103*49cdfc7eSAndroid Build Coastguard Worker        """Check whether a given ltp lib module in Android.mk file
104*49cdfc7eSAndroid Build Coastguard Worker           is succesfully built
105*49cdfc7eSAndroid Build Coastguard Worker
106*49cdfc7eSAndroid Build Coastguard Worker           Args:
107*49cdfc7eSAndroid Build Coastguard Worker               module_path: the path of module on the first line of
108*49cdfc7eSAndroid Build Coastguard Worker                            the block
109*49cdfc7eSAndroid Build Coastguard Worker
110*49cdfc7eSAndroid Build Coastguard Worker           Returns:
111*49cdfc7eSAndroid Build Coastguard Worker               True if success
112*49cdfc7eSAndroid Build Coastguard Worker        """
113*49cdfc7eSAndroid Build Coastguard Worker        # TODO(yuexima) check lib build
114*49cdfc7eSAndroid Build Coastguard Worker        print("Checking module_lib is not supported now, " + \
115*49cdfc7eSAndroid Build Coastguard Worker            "assuming build success: " + self._path)
116*49cdfc7eSAndroid Build Coastguard Worker        return True
117*49cdfc7eSAndroid Build Coastguard Worker
118*49cdfc7eSAndroid Build Coastguard Worker    def IsBuildSuccessModulePrebuilt(self):
119*49cdfc7eSAndroid Build Coastguard Worker        """Check whether a given prebuilt module in Android.mk file
120*49cdfc7eSAndroid Build Coastguard Worker           is succesfully built
121*49cdfc7eSAndroid Build Coastguard Worker
122*49cdfc7eSAndroid Build Coastguard Worker           Args:
123*49cdfc7eSAndroid Build Coastguard Worker               module_path: string, the path of module on the first
124*49cdfc7eSAndroid Build Coastguard Worker                            line of the block
125*49cdfc7eSAndroid Build Coastguard Worker
126*49cdfc7eSAndroid Build Coastguard Worker           Returns:
127*49cdfc7eSAndroid Build Coastguard Worker               True if success
128*49cdfc7eSAndroid Build Coastguard Worker        """
129*49cdfc7eSAndroid Build Coastguard Worker        return os.path.isfile(self._output_dir + self._path)
130*49cdfc7eSAndroid Build Coastguard Worker
131*49cdfc7eSAndroid Build Coastguard Worker
132*49cdfc7eSAndroid Build Coastguard Workerclass LtpModuleChecker(object):
133*49cdfc7eSAndroid Build Coastguard Worker    """LTP module result check class.
134*49cdfc7eSAndroid Build Coastguard Worker    Checks for success build of each module in LTP's Android.mk file
135*49cdfc7eSAndroid Build Coastguard Worker    and rewrite it with only successfully built modules.
136*49cdfc7eSAndroid Build Coastguard Worker    """
137*49cdfc7eSAndroid Build Coastguard Worker    _output_dir = ""
138*49cdfc7eSAndroid Build Coastguard Worker    _file_path_android_ltp_mk = ""
139*49cdfc7eSAndroid Build Coastguard Worker    _module_counts = {}
140*49cdfc7eSAndroid Build Coastguard Worker
141*49cdfc7eSAndroid Build Coastguard Worker    def __init__(self, android_build_top, ltp_dir, target_product):
142*49cdfc7eSAndroid Build Coastguard Worker        self._output_dir = android_build_top + '/out/target/product/' + \
143*49cdfc7eSAndroid Build Coastguard Worker                          target_product + '/data/nativetest/ltp/'
144*49cdfc7eSAndroid Build Coastguard Worker        self._file_path_android_ltp_mk = ltp_dir + '/Android.ltp.mk'
145*49cdfc7eSAndroid Build Coastguard Worker
146*49cdfc7eSAndroid Build Coastguard Worker    def Read(self, file_path):
147*49cdfc7eSAndroid Build Coastguard Worker        """Read a file and return its entire content
148*49cdfc7eSAndroid Build Coastguard Worker
149*49cdfc7eSAndroid Build Coastguard Worker           Args:
150*49cdfc7eSAndroid Build Coastguard Worker               file_path: string, file path
151*49cdfc7eSAndroid Build Coastguard Worker
152*49cdfc7eSAndroid Build Coastguard Worker           Returns:
153*49cdfc7eSAndroid Build Coastguard Worker               entire file content in string format
154*49cdfc7eSAndroid Build Coastguard Worker        """
155*49cdfc7eSAndroid Build Coastguard Worker        with open(file_path, 'r') as file:
156*49cdfc7eSAndroid Build Coastguard Worker            return file.read()
157*49cdfc7eSAndroid Build Coastguard Worker
158*49cdfc7eSAndroid Build Coastguard Worker    def LoadModules(self):
159*49cdfc7eSAndroid Build Coastguard Worker        """Read the LTP Android.mk file and seperate modules into
160*49cdfc7eSAndroid Build Coastguard Worker           a list of string
161*49cdfc7eSAndroid Build Coastguard Worker        """
162*49cdfc7eSAndroid Build Coastguard Worker        return self.Read(self._file_path_android_ltp_mk).split("\n\n")
163*49cdfc7eSAndroid Build Coastguard Worker
164*49cdfc7eSAndroid Build Coastguard Worker    def CheckModules(self):
165*49cdfc7eSAndroid Build Coastguard Worker        """Start the LTP module build result checking and counting."""
166*49cdfc7eSAndroid Build Coastguard Worker        modules = [Module(self._output_dir).parse(module)
167*49cdfc7eSAndroid Build Coastguard Worker                   for module in self.LoadModules()]
168*49cdfc7eSAndroid Build Coastguard Worker        modules_succeed = \
169*49cdfc7eSAndroid Build Coastguard Worker            [module for module in modules
170*49cdfc7eSAndroid Build Coastguard Worker             if module is not None and
171*49cdfc7eSAndroid Build Coastguard Worker             module.IsBuildSuccess(self._module_counts)
172*49cdfc7eSAndroid Build Coastguard Worker            ]
173*49cdfc7eSAndroid Build Coastguard Worker
174*49cdfc7eSAndroid Build Coastguard Worker        print("module type counts:")
175*49cdfc7eSAndroid Build Coastguard Worker        print(self._module_counts)
176*49cdfc7eSAndroid Build Coastguard Worker
177*49cdfc7eSAndroid Build Coastguard Worker        print(str(len(modules_succeed)) + \
178*49cdfc7eSAndroid Build Coastguard Worker              " of " + str(sum([self._module_counts[i]
179*49cdfc7eSAndroid Build Coastguard Worker              for i in self._module_counts])) + \
180*49cdfc7eSAndroid Build Coastguard Worker              " modules were succesfully built.")
181*49cdfc7eSAndroid Build Coastguard Worker        print("--Check complete.")
182*49cdfc7eSAndroid Build Coastguard Worker
183*49cdfc7eSAndroid Build Coastguard Worker
184*49cdfc7eSAndroid Build Coastguard Workerdef main():
185*49cdfc7eSAndroid Build Coastguard Worker    parser = argparse.ArgumentParser(
186*49cdfc7eSAndroid Build Coastguard Worker        description='Generate Android.mk from parsed LTP make output')
187*49cdfc7eSAndroid Build Coastguard Worker    parser.add_argument(
188*49cdfc7eSAndroid Build Coastguard Worker        '--android_build_top',
189*49cdfc7eSAndroid Build Coastguard Worker        dest='android_build_top',
190*49cdfc7eSAndroid Build Coastguard Worker        required=True,
191*49cdfc7eSAndroid Build Coastguard Worker        help='android build top directory')
192*49cdfc7eSAndroid Build Coastguard Worker    parser.add_argument(
193*49cdfc7eSAndroid Build Coastguard Worker        '--ltp_dir',
194*49cdfc7eSAndroid Build Coastguard Worker        dest='ltp_dir',
195*49cdfc7eSAndroid Build Coastguard Worker        required=True,
196*49cdfc7eSAndroid Build Coastguard Worker        help='directory for the forked ltp project')
197*49cdfc7eSAndroid Build Coastguard Worker    parser.add_argument(
198*49cdfc7eSAndroid Build Coastguard Worker        '--target_product',
199*49cdfc7eSAndroid Build Coastguard Worker        dest='target_product',
200*49cdfc7eSAndroid Build Coastguard Worker        required=True,
201*49cdfc7eSAndroid Build Coastguard Worker        help='target product name, \
202*49cdfc7eSAndroid Build Coastguard Worker                                such as "bullhead", "angler", etc.')
203*49cdfc7eSAndroid Build Coastguard Worker    args = parser.parse_args()
204*49cdfc7eSAndroid Build Coastguard Worker
205*49cdfc7eSAndroid Build Coastguard Worker    checker = LtpModuleChecker(args.android_build_top, args.ltp_dir,
206*49cdfc7eSAndroid Build Coastguard Worker                               args.target_product)
207*49cdfc7eSAndroid Build Coastguard Worker    checker.CheckModules()
208*49cdfc7eSAndroid Build Coastguard Worker
209*49cdfc7eSAndroid Build Coastguard Worker
210*49cdfc7eSAndroid Build Coastguard Workerif __name__ == '__main__':
211*49cdfc7eSAndroid Build Coastguard Worker    main()
212