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 stat
21
22from xdevice import platform_logger
23from core.utils import scan_support_product
24from core.config.config_manager import UserConfigManager, FrameworkConfigManager
25from core.build.select_targets import SelectTargets
26from core.build.pretreat_targets import PretreatTargets
27from core.build.build_testcases import BuildTestcases
28from core.command.gen import Gen
29from core.command.run import Run
30
31FLAGS = os.O_WRONLY | os.O_APPEND | os.O_CREAT
32MODES = stat.S_IWUSR | stat.S_IRUSR
33
34LOG = platform_logger("BuildManager")
35
36
37##############################################################################
38##############################################################################
39
40class BuildManager(object):
41    @classmethod
42    def build_version(cls, project_root_path, product_form):
43        if BuildTestcases(project_root_path).build_version(product_form):
44            LOG.info("The version compiled successfully.")
45            build_result = True
46        else:
47            LOG.info("The version compilation failed, please modify.")
48            build_result = False
49        return build_result
50
51    @classmethod
52    def build_gn_file(cls, project_root_path, product_form):
53        if BuildTestcases(project_root_path).build_gn_file(product_form):
54            LOG.info("The gn compiled successfully.")
55            build_result = True
56        else:
57            LOG.info("The gn compilation failed, please modify.")
58            build_result = False
59        return build_result
60
61    @classmethod
62    def _make_gn_file(cls, filepath, target_list):
63        LOG.info("The gn file path: %s" % filepath)
64        if os.path.exists(filepath):
65            os.remove(filepath)
66        with os.fdopen(os.open(filepath, FLAGS, MODES), 'w') as gn_file:
67            gn_file.write("group(\"make_temp_test\") {\n")
68            gn_file.write("  testonly = true\n")
69            gn_file.write("  deps = []\n")
70            if target_list:
71                gn_file.write("  deps += [\n")
72                for target in target_list:
73                    if target:
74                        gn_file.write("    \"%s\",\n" % target)
75                gn_file.write("  ]\n")
76            gn_file.write("}\n")
77
78    # 根据目标编译测试用例
79    # project_root_path 工程根目录
80    # product_form 产品形态,指令第一步选择的产品
81    # build_target 编译目标
82    @classmethod
83    def _compile_test_cases_by_target(cls, project_root_path, product_form,
84                                      build_target):
85        if BuildTestcases(project_root_path).build_testcases(product_form,
86                                                             build_target):
87            LOG.info("Test case compilation successed.")
88            build_result = True
89        else:
90            LOG.info("Test case compilation failed, please modify.")
91            build_result = False
92        return build_result
93
94    # 根据json生成部件间依赖关系
95    # para 指令参数
96    # 编译代码生成中间文件,只执行gn阶段,并打开check_deps属性
97
98    @classmethod
99    def _compile_deps_files(cls, project_root_path, para):
100        build_deps_files_result = False
101        if BuildTestcases(project_root_path).build_deps_files(para.productform):
102            LOG.info("Deps files compilation successed.")
103            build_deps_files_result = True
104        else:
105            LOG.info("Deps files compilation failed, please modify.")
106        return build_deps_files_result
107
108    # 运行脚本,生成part_deps_info.json部件间依赖关系文件
109    @classmethod
110    def _compile_part_deps(cls, project_root_path, para):
111        build_part_deps_result = False
112        if BuildTestcases(project_root_path).build_part_deps(para):
113            LOG.info("Part deps info compilation successed.")
114            build_part_deps_result = True
115        else:
116            LOG.info("Part deps info compilation failed, please modify.")
117        return build_part_deps_result
118
119    # 根据目标编译xts测试用例
120    # project_root_path 工程根目录
121    # para 指令参数
122    @classmethod
123    def _compile_xts_test_cases(cls, project_root_path, para):
124        if BuildTestcases(project_root_path).build_xts_testcases(para):
125            LOG.info("XTS test case compilation successed.")
126            build_result = True
127        else:
128            LOG.info("XTS test compilation failed, please modify.")
129            build_result = False
130        return build_result
131
132    @classmethod
133    def _compile_fuzz_test_case(cls, project_root_path, para):
134        build_result = BuildTestcases(
135            project_root_path).build_fuzz_testcases(para)
136        if build_result:
137            LOG.info("Test case compilation successed.")
138        else:
139            LOG.info("Test case compilation failed, please modify.")
140        return build_result
141
142    def build_testcases(self, project_root_path, param):
143        if not os.path.exists(project_root_path):
144            LOG.error("%s is not exists." % project_root_path)
145            return False
146
147        LOG.info("--------------------------------------------------")
148        LOG.info("Building parameter:")
149        LOG.info("productform   = %s" % param.productform)
150        LOG.info("testtype      = %s" % str(param.testtype))
151        LOG.info("partname_list = %s" % str(param.partname_list))
152        LOG.info("testmodule    = %s" % param.testmodule)
153        LOG.info("testsuit      = %s" % param.testsuit)
154        LOG.info("testcase      = %s" % param.testcase)
155        LOG.info("--------------------------------------------------")
156
157        LOG.info("")
158        LOG.info("**************************************************")
159        LOG.info("*************** Start build testcases ************")
160        LOG.info("**************************************************")
161        LOG.info("")
162
163        build_xts_result = True
164        build_result = True
165        if "partdeps" == param.partdeps:
166            LOG.info("**********************Start prebuild testcases****************************")
167            build_deps_files_result = self._compile_deps_files(project_root_path, param)
168            if build_deps_files_result:
169                self._compile_part_deps(project_root_path, param)
170
171        if "acts" in param.testtype or "hats" in param.testtype or "hits" in param.testtype:
172            LOG.info("**********************Start build xts testcases****************************")
173            build_xts_result = self._compile_xts_test_cases(project_root_path, param)
174        else:
175            LOG.info("**********************Start build subsystem testcases****************************")
176            build_result = self._compile_testcases(project_root_path, param)
177
178        LOG.info("")
179        LOG.info("**************************************************")
180        LOG.info("*************** Ended build testcases ************")
181        LOG.info("**************************************************")
182        LOG.info("")
183
184        return build_result and build_xts_result
185
186     # 编译入口
187
188    def _compile_testcases(self, project_root_path, para):
189        # 获取所有支持的产品,3.1Release版本为["DAYU","Hi3516DV300","ohos-arm64","ohos-sdk","rk3568"]
190        all_product_list = scan_support_product()
191        product_list = FrameworkConfigManager().get_framework_config("productform")
192        if para.productform in product_list and para.productform.find("wifiiot") == -1:
193            all_product_list.append(para.productform)
194        if para.productform not in all_product_list:
195            from core.build.build_lite_manager import BuildLiteManager
196            build_lite_manager = BuildLiteManager(project_root_path)
197            return build_lite_manager.build_testcases(para)
198
199        # 如果测试集不为空或测试部件不为空,build_target为测试集或测试部件
200        # 如果测试集不为空,build_target为测试集
201        if para.testsuit != "":
202            return self._compile_test_cases_by_target(
203                project_root_path,
204                para.productform,
205                para.testsuit)
206        if para.partname_list != "":
207            if "partdeps" == para.partdeps:
208                LOG.info("External deps part build.")
209                external_deps_part_list = Run.get_part_deps_list(para.productform, para.testpart)
210                external_deps_part_list.append(para.testpart[0])
211                return self._compile_test_cases_by_target(
212                    project_root_path,
213                    para.productform,
214                    external_deps_part_list)
215            else:
216                LOG.info("Multi testpart build.")
217                return self._compile_test_cases_by_target(
218                    project_root_path,
219                    para.productform,
220                    para.partname_list)
221
222        # 如果测试集为空,部件列表为空,模块列表为空,测试类型中含有“ALL”,build_target为"make_test"
223        if (len(para.partname_list) == 0 and para.testmodule == "" and
224                "ALL" in para.testtype):
225            return self._compile_test_cases_by_target(
226                project_root_path,
227                para.productform,
228                "make_test")
229
230        # 如果测试集为空,三个条件(部件列表为空,模块列表为空,测试类型中含有“ALL”)不同时成立
231        target_list = SelectTargets(
232            project_root_path).filter_build_targets(para)
233        if len(target_list) == 0:
234            LOG.warning("No build target found.")
235            return False
236
237        # 路径拼接 build_cfg_filepath = OpenHarmony/test/testfwk/developer_test/BUILD.gn
238        build_cfg_filepath = os.path.join(project_root_path,
239                                          "test",
240                                          "testfwk",
241                                          "developer_test",
242                                          "BUILD.gn")
243
244        self._make_gn_file(build_cfg_filepath, target_list)
245        if "fuzztest" in para.testtype:
246            Gen().gen_fuzzer_list_file(target_list)
247            build_result = self._compile_fuzz_test_case(
248                project_root_path, para)
249        else:
250            build_result = self._compile_test_cases_by_target(
251                project_root_path,
252                para.productform,
253                "make_temp_test")
254        self._make_gn_file(build_cfg_filepath, [])
255
256        return build_result
257
258##############################################################################
259##############################################################################
260