• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3
4#
5# Copyright (c) 2020-2022 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import os
20import sys
21import json
22import shutil
23import subprocess
24import platform
25
26from xdevice import platform_logger
27from core.utils import get_build_output_path
28from core.utils import get_output_path
29from core.utils import scan_support_product
30from core.common import is_open_source_product
31from core.config.config_manager import UserConfigManager
32
33BUILD_FILE_PATH = "./build_system.sh"
34BUILD_FILEPATH = "./build.sh"
35BUILD_LITE = "build/lite/build.py"
36BUILD_TARGET_PLATFORM = "build_platform=\"%s\""
37BUILD_PRODUCT_NAME = "product_name=%s"
38BUILD_TARGET_SUBSYSTEM = "target_subsystem=%s"
39BUILD_TARGET_SUITE = "suite=%s"
40LOG = platform_logger("BuildTestcases")
41
42
43##############################################################################
44##############################################################################
45
46class BuildTestcases(object):
47    def __init__(self, project_rootpath):
48        self.project_rootpath = project_rootpath
49        user_manager = UserConfigManager()
50        self.part_deps_path = os.path.join(sys.source_code_root_path,
51                                           "build",
52                                           "tools",
53                                           "module_dependence",
54                                           "part_deps.py")
55        self.is_build_example = user_manager.get_user_config_flag(
56            "build", "example")
57        self.build_parameter_dic = user_manager.get_user_config(
58            "build", "parameter")
59
60    @classmethod
61    def _copy_folder(cls, source_dir, target_dir):
62        if not os.path.exists(target_dir):
63            os.makedirs(target_dir)
64
65        if platform.system() == 'Windows':
66            command = ["xcopy", "/f", "/s", "/e", "/y",
67                       "/b", "/q", source_dir, target_dir]
68        else:
69            command = ["cp", "-rf", source_dir, target_dir]
70
71        LOG.info("command: %s" % str(command))
72        return subprocess.call(command) == 0
73
74    @classmethod
75    def _get_testcase_outname_by_productform(cls, productform):
76        if productform == "phone" or is_open_source_product(productform):
77            return ""
78
79        testcase_outpath = ""
80
81        # 路径注释 get_build_output_path = OpenHarmony/out/rk3568/build_configs/platforms_info/toolchain_to_variant.json
82        toolchain_filepath = os.path.join(
83            get_build_output_path(productform),
84            "build_configs",
85            "platforms_info",
86            "toolchain_to_variant.json")
87        if os.path.exists(toolchain_filepath):
88            data_dic = []
89            with open(toolchain_filepath, 'r') as toolchain_file:
90                data_dic = json.load(toolchain_file)
91                if not data_dic:
92                    LOG.warning("The %s file load error." %
93                                toolchain_filepath)
94                    data_dic = []
95            paltform_toolchain_dic = data_dic.get("platform_toolchain")
96            testcase_outpath = paltform_toolchain_dic.get(productform, "")
97            pos = testcase_outpath.rfind(':') + 1
98            testcase_outpath = testcase_outpath[pos:len(testcase_outpath)]
99        return testcase_outpath
100
101    @classmethod
102    def _delete_xts_testcase_dir(cls, para):
103        xts_testcase_out_dir = os.path.join(
104            get_build_output_path(para.productform),
105            "suites",
106            para.testtype[0],
107            "testcases")
108        LOG.info("xts_testcase_out_dir=%s" % xts_testcase_out_dir)
109        # 删除~/OpenHarmony/out/rk3568/suites/xts/testcases目录内容
110        if os.path.exists(xts_testcase_out_dir):
111            shutil.rmtree(xts_testcase_out_dir)
112
113    def _delete_testcase_dir(self, productform):
114        if is_open_source_product(productform):
115            package_out_dir = os.path.join(
116                get_build_output_path(productform),
117                "packages",
118                "phone",
119                "tests")
120        else:
121            package_out_dir = os.path.join(
122                get_build_output_path(productform),
123                "packages",
124                productform,
125                "tests")
126
127        LOG.info("package_out_dir=%s" % package_out_dir)
128        # 删除~/OpenHarmony/out/rk3568/packages/phone/tests目录内容
129        if os.path.exists(package_out_dir):
130            shutil.rmtree(package_out_dir)
131
132        phone_out_dir = os.path.join(
133            self.project_rootpath, "out", "release", "tests")
134        LOG.info("phone_out_dir=%s" % phone_out_dir)
135        # 删除~/OpenHarmony/out/release/tests目录内容
136        if os.path.exists(phone_out_dir):
137            shutil.rmtree(phone_out_dir)
138
139        curr_productform_outname = self._get_testcase_outname_by_productform(
140            productform)
141        if curr_productform_outname == "":
142            return
143
144        curr_productform_outdir = os.path.join(
145            get_build_output_path(productform),
146            curr_productform_outname,
147            "tests")
148        LOG.info("curr_productform_outdir=%s" % curr_productform_outdir)
149        if os.path.exists(curr_productform_outdir):
150            shutil.rmtree(curr_productform_outdir)
151
152    def _merge_testcase_dir(self, productform):
153        if is_open_source_product(productform):
154            package_out_dir = os.path.join(
155                get_build_output_path(productform),
156                "packages",
157                "phone")
158        else:
159            package_out_dir = os.path.join(
160                get_build_output_path(productform),
161                "packages",
162                productform)
163        if platform.system() == 'Windows':
164            package_out_dir = os.path.join(package_out_dir, "tests")
165
166        phone_out_dir = os.path.join(get_build_output_path(productform),
167                                     "tests")
168        if os.path.exists(phone_out_dir):
169            self._copy_folder(phone_out_dir, package_out_dir)
170
171        curr_productform_outname = self._get_testcase_outname_by_productform(
172            productform)
173        if curr_productform_outname == "":
174            return
175
176        curr_productform_outdir = os.path.join(
177            get_build_output_path(productform),
178            curr_productform_outname,
179            "tests")
180        LOG.info("curr_productform_outdir=%s" % curr_productform_outdir)
181        if os.path.exists(curr_productform_outdir):
182            self._copy_folder(curr_productform_outdir, package_out_dir)
183
184    def _execute_build_command(self, productform, command):
185        build_result = False
186        current_path = os.getcwd()
187        os.chdir(self.project_rootpath)
188
189        if productform == "rk3568":
190            command.append("--product-name")
191            command.append(productform)
192        else:
193            global BUILD_FILEPATH
194            BUILD_FILEPATH = BUILD_FILE_PATH
195
196        if os.path.exists(BUILD_FILEPATH):
197            build_command = [BUILD_FILEPATH]
198            build_command.extend(command)
199            LOG.info("build_command: %s" % str(build_command))
200            if subprocess.call(build_command) == 0:
201                build_result = True
202            else:
203                build_result = False
204        else:
205            LOG.warning("Error: The %s is not exist" % BUILD_FILEPATH)
206
207        os.chdir(current_path)
208        return build_result
209
210    def _execute_build_deps_files_command(self, productform, command):
211        build_deps_files_result = False
212        current_path = os.getcwd()
213        os.chdir(self.project_rootpath)
214
215        if productform == "rk3568":
216            command.append("--product-name")
217            command.append(productform)
218        else:
219            global BUILD_FILEPATH
220            BUILD_FILEPATH = BUILD_FILE_PATH
221
222        if os.path.exists(BUILD_FILEPATH):
223            build_deps_files_command = [BUILD_FILEPATH]
224            build_deps_files_command.extend(command)
225            LOG.info("build_deps_files_command: %s" % str(build_deps_files_command))
226            if subprocess.call(build_deps_files_command) == 0:
227                build_deps_files_result = True
228            else:
229                build_deps_files_result = False
230        else:
231            LOG.warning("Build Deps Files Error: The %s is not exist" % BUILD_FILEPATH)
232
233        os.chdir(current_path)
234        return build_deps_files_result
235
236    def _execute_build_part_deps_command(self, para):
237        build_part_deps_result = False
238        build_part_deps_command = []
239        current_path = os.getcwd()
240        # 路径 deps_files_path = ~/OpenHarmony/out/baltimore/deps_files
241        os.chdir(self.project_rootpath)
242        if para.productform == "rk3568":
243            deps_files_path = os.path.abspath(os.path.join(
244                get_build_output_path(para.productform), "deps_files"))
245        else:
246            deps_files_path = os.path.abspath(os.path.join(
247                "out", get_output_path(), "deps_files"))
248        LOG.info("deps_files_path: %s" % deps_files_path)
249        build_part_deps_command.append(self.part_deps_path)
250        build_part_deps_command.append("--deps-files-path")
251
252        if os.path.exists(deps_files_path):
253            build_part_deps_command.append(deps_files_path)
254            LOG.info("build_part_deps_command: %s" % str(build_part_deps_command))
255            if subprocess.call(build_part_deps_command) == 0:
256                build_part_deps_result = True
257            else:
258                build_part_deps_result = False
259        else:
260            LOG.warning("Build Part Deps Info Error: The %s is not exist" % deps_files_path)
261
262        os.chdir(current_path)
263        return build_part_deps_result
264
265    def _execute_build_xts_command(self, para, xts_build_command):
266        build_result = False
267        current_path = os.getcwd()
268        # eg.路径 acts_rootpath = ~/OpenHarmony/test/xts/acts
269        xts_project_rootpath = os.path.join(sys.source_code_root_path,
270                                            "test",
271                                            "xts",
272                                            para.testtype[0])
273        os.chdir(self.project_rootpath)
274        if para.productform == "rk3568":
275            os.chdir(xts_project_rootpath)
276            xts_build_command.append(BUILD_PRODUCT_NAME % para.productform)
277            xts_build_command.append("system_size=standard")
278            if len(para.subsystem) > 0:
279                input_subsystem = ",".join(para.subsystem)
280                xts_build_command.append(BUILD_TARGET_SUBSYSTEM % input_subsystem)
281            if para.testsuit != "" and len(para.subsystem) == 0:
282                LOG.error("Please specify subsystem.")
283                return False
284        else:
285            global BUILD_FILEPATH
286            BUILD_FILEPATH = BUILD_FILE_PATH
287
288        if os.path.exists(BUILD_FILEPATH):
289            build_command = [BUILD_FILEPATH]
290            build_command.extend(xts_build_command)
291            LOG.info("build_xts_command: %s" % str(build_command))
292            if subprocess.call(build_command) == 0:
293                build_result = True
294            else:
295                build_result = False
296        else:
297            LOG.warning("Build XTS Testcase Error: The %s is not exist" % BUILD_FILEPATH)
298
299        os.chdir(current_path)
300        return build_result
301
302    def build_fuzz_testcases(self, para):
303        self._delete_testcase_dir(para.productform)
304        helper_path = os.path.join("..", "libs", "fuzzlib", "fuzzer_helper.py")
305        command = [sys.executable, helper_path, 'make',
306                   'make_temp_test', para.productform]
307        if subprocess.call(command, shell=False) == 0:
308            build_result = True
309        else:
310            build_result = False
311        self._merge_testcase_dir(para.productform)
312        return build_result
313
314    # 编译测试用例(编译命令拼接)
315    def build_testcases(self, productform, target):
316        command = []
317        if self.is_build_example:
318            command.append("--gn-args")
319            command.append("build_example=true")
320        if isinstance(target, list):
321            for test in target:
322                command.append("--build-target")
323                command.append(test + "_test")
324        elif isinstance(target, str):
325            for test in target.split(','):
326                command.append("--build-target")
327                command.append(test)
328
329        if productform == "rk3568":
330            pass
331        else:
332            command.append("--abi-type")
333            command.append("generic_generic_arm_64only")
334            command.append("--device-type")
335            command.append(get_output_path().split("/")[-1])
336            command.append("--build-variant")
337            command.append("root")
338        command.append("--ccache")
339        self._delete_testcase_dir(productform)
340        build_result = self._execute_build_command(productform, command)
341        self._merge_testcase_dir(productform)
342        return build_result
343
344    # 编译XTS测试用例
345    def build_xts_testcases(self, para):
346        self._delete_xts_testcase_dir(para)
347        xts_build_command = []
348        if para.productform == "rk3568":
349            pass
350        else:
351            xts_build_test_command = ["--abi-type", "generic_generic_arm_64only", "--device-type",
352                                      get_output_path().split("/")[-1], "--build-variant", "root", "--gn-args",
353                                      "build_xts=true", "--export-para", "xts_suitename:" + para.testtype[0]]
354            if len(para.subsystem) > 0:
355                input_subsystem = ",".join(para.subsystem)
356                xts_build_test_command.append("--build-target")
357                xts_build_test_command.append(input_subsystem)
358            if para.testsuit != "" and len(para.subsystem) == 0:
359                LOG.error("Please specify subsystem.")
360                return
361            xts_build_command.extend(xts_build_test_command)
362            xts_build_command.append("--ccache")
363        build_result = self._execute_build_xts_command(para, xts_build_command)
364        return build_result
365
366
367    def build_deps_files(self, productform):
368        command = ["--ccache", "--gn-args", "pycache_enable=true", "--gn-args",
369                   "check_deps=true", "--build-only-gn"]
370        if productform == "rk3568":
371            pass
372        else:
373            command.append("--abi-type")
374            command.append("generic_generic_arm_64only")
375            command.append("--device-type")
376            command.append(get_output_path().split("/")[-1])
377            command.append("--build-variant")
378            command.append("root")
379        return self._execute_build_deps_files_command(productform, command)
380
381    # 部件间依赖关系预处理,生成part_deps_info.json
382    def build_part_deps(self, para):
383        build_part_deps_result = self._execute_build_part_deps_command(para)
384        return build_part_deps_result
385
386    def build_gn_file(self, productform):
387        command = []
388        if self.is_build_example:
389            command.append("--gn-args")
390            command.append("build_example=true")
391        command.append("--build-only-gn")
392        command.append("--gn-args")
393        command.append(BUILD_TARGET_PLATFORM % productform)
394        return self._execute_build_command(productform, command)
395
396    def build_version(self, productform):
397        command = []
398        command.append("--build-target")
399        command.append("make_all")
400        command.append("--gn-args")
401        command.append(BUILD_TARGET_PLATFORM % productform)
402        return self._execute_build_command(productform, command)
403
404##############################################################################
405##############################################################################
406