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 build_fuzz_testcases(self, para): 114 self._delete_testcase_dir(para.productform) 115 helper_path = os.path.join("..", "libs", "fuzzlib", "fuzzer_helper.py") 116 command = [sys.executable, helper_path, 'make', 117 'make_temp_test', para.productform] 118 if subprocess.call(command, shell=False) == 0: 119 build_result = True 120 else: 121 build_result = False 122 self._merge_testcase_dir(para.productform) 123 return build_result 124 125 # 编译测试用例(编译命令拼接) 126 def build_testcases(self, productform, target): 127 command = [] 128 if self.is_build_example: 129 command.append("--gn-args") 130 command.append("build_example=true") 131 if isinstance(target, list): 132 for test in target: 133 command.append("--build-target") 134 command.append(test + "_test") 135 elif isinstance(target, str): 136 for test in target.split(','): 137 command.append("--build-target") 138 command.append(test) 139 140 if productform == "rk3568": 141 pass 142 else: 143 command.append("--abi-type") 144 command.append("generic_generic_arm_64only") 145 command.append("--device-type") 146 command.append(get_output_path().split("/")[-1]) 147 command.append("--build-variant") 148 command.append("root") 149 command.append("--ccache") 150 self._delete_testcase_dir(productform) 151 build_result = self._execute_build_command(productform, command) 152 self._merge_testcase_dir(productform) 153 return build_result 154 155 # 编译XTS测试用例 156 def build_xts_testcases(self, para): 157 self._delete_xts_testcase_dir(para) 158 xts_build_command = [] 159 if para.productform == "rk3568": 160 False 161 else: 162 xts_build_test_command = ["--abi-type", "generic_generic_arm_64only", "--device-type", 163 get_output_path().split("/")[-1], "--build-variant", "root", "--gn-args", 164 "build_xts=true", "--export-para", "xts_suitename:" + para.testtype[0]] 165 if len(para.subsystem) > 0: 166 input_subsystem = ",".join(para.subsystem) 167 xts_build_test_command.append("--build-target") 168 xts_build_test_command.append(input_subsystem) 169 return False 170 if para.testsuit != "" and len(para.subsystem) == 0: 171 LOG.error("Please specify subsystem.") 172 return False 173 xts_build_command.extend(xts_build_test_command) 174 xts_build_command.append("--ccache") 175 build_result = self._execute_build_xts_command(para, xts_build_command) 176 return build_result 177 178 179 def build_deps_files(self, productform): 180 command = ["--ccache", "--gn-args", "pycache_enable=true", "--gn-args", 181 "check_deps=true", "--build-only-gn"] 182 if productform == "rk3568": 183 pass 184 else: 185 command.append("--abi-type") 186 command.append("generic_generic_arm_64only") 187 command.append("--device-type") 188 command.append(get_output_path().split("/")[-1]) 189 command.append("--build-variant") 190 command.append("root") 191 return self._execute_build_deps_files_command(productform, command) 192 193 # 部件间依赖关系预处理,生成part_deps_info.json 194 def build_part_deps(self, para): 195 build_part_deps_result = self._execute_build_part_deps_command(para) 196 return build_part_deps_result 197 198 def build_gn_file(self, productform): 199 command = [] 200 if self.is_build_example: 201 command.append("--gn-args") 202 command.append("build_example=true") 203 command.append("--build-only-gn") 204 command.append("--gn-args") 205 command.append(BUILD_TARGET_PLATFORM % productform) 206 return self._execute_build_command(productform, command) 207 208 def build_version(self, productform): 209 command = [] 210 command.append("--build-target") 211 command.append("make_all") 212 command.append("--gn-args") 213 command.append(BUILD_TARGET_PLATFORM % productform) 214 return self._execute_build_command(productform, command) 215 216 def _delete_testcase_dir(self, productform): 217 if is_open_source_product(productform): 218 package_out_dir = os.path.join( 219 get_build_output_path(productform), 220 "packages", 221 "phone", 222 "tests") 223 else: 224 package_out_dir = os.path.join( 225 get_build_output_path(productform), 226 "packages", 227 productform, 228 "tests") 229 230 LOG.info("package_out_dir=%s" % package_out_dir) 231 # 删除~/OpenHarmony/out/rk3568/packages/phone/tests目录内容 232 if os.path.exists(package_out_dir): 233 shutil.rmtree(package_out_dir) 234 235 phone_out_dir = os.path.join( 236 self.project_rootpath, "out", "release", "tests") 237 LOG.info("phone_out_dir=%s" % phone_out_dir) 238 # 删除~/OpenHarmony/out/release/tests目录内容 239 if os.path.exists(phone_out_dir): 240 shutil.rmtree(phone_out_dir) 241 242 curr_productform_outname = self._get_testcase_outname_by_productform( 243 productform) 244 if curr_productform_outname == "": 245 return 246 247 curr_productform_outdir = os.path.join( 248 get_build_output_path(productform), 249 curr_productform_outname, 250 "tests") 251 LOG.info("curr_productform_outdir=%s" % curr_productform_outdir) 252 if os.path.exists(curr_productform_outdir): 253 shutil.rmtree(curr_productform_outdir) 254 255 def _merge_testcase_dir(self, productform): 256 if is_open_source_product(productform): 257 package_out_dir = os.path.join( 258 get_build_output_path(productform), 259 "packages", 260 "phone") 261 else: 262 package_out_dir = os.path.join( 263 get_build_output_path(productform), 264 "packages", 265 productform) 266 if platform.system() == 'Windows': 267 package_out_dir = os.path.join(package_out_dir, "tests") 268 269 phone_out_dir = os.path.join(get_build_output_path(productform), 270 "tests") 271 if os.path.exists(phone_out_dir): 272 self._copy_folder(phone_out_dir, package_out_dir) 273 274 curr_productform_outname = self._get_testcase_outname_by_productform( 275 productform) 276 if curr_productform_outname == "": 277 return 278 279 curr_productform_outdir = os.path.join( 280 get_build_output_path(productform), 281 curr_productform_outname, 282 "tests") 283 LOG.info("curr_productform_outdir=%s" % curr_productform_outdir) 284 if os.path.exists(curr_productform_outdir): 285 self._copy_folder(curr_productform_outdir, package_out_dir) 286 287 def _execute_build_command(self, productform, command): 288 build_result = False 289 current_path = os.getcwd() 290 os.chdir(self.project_rootpath) 291 292 if productform == "rk3568": 293 command.append("--product-name") 294 command.append(productform) 295 else: 296 global BUILD_FILEPATH 297 BUILD_FILEPATH = BUILD_FILE_PATH 298 299 if os.path.exists(BUILD_FILEPATH): 300 build_command = [BUILD_FILEPATH] 301 build_command.extend(command) 302 LOG.info("build_command: %s" % str(build_command)) 303 if subprocess.call(build_command) == 0: 304 build_result = True 305 else: 306 build_result = False 307 else: 308 LOG.warning("Error: The %s is not exist" % BUILD_FILEPATH) 309 310 os.chdir(current_path) 311 return build_result 312 313 def _execute_build_deps_files_command(self, productform, command): 314 build_deps_files_result = False 315 current_path = os.getcwd() 316 os.chdir(self.project_rootpath) 317 318 if productform == "rk3568": 319 command.append("--product-name") 320 command.append(productform) 321 else: 322 global BUILD_FILEPATH 323 BUILD_FILEPATH = BUILD_FILE_PATH 324 325 if os.path.exists(BUILD_FILEPATH): 326 build_deps_files_command = [BUILD_FILEPATH] 327 build_deps_files_command.extend(command) 328 LOG.info("build_deps_files_command: %s" % str(build_deps_files_command)) 329 if subprocess.call(build_deps_files_command) == 0: 330 build_deps_files_result = True 331 else: 332 build_deps_files_result = False 333 else: 334 LOG.warning("Build Deps Files Error: The %s is not exist" % BUILD_FILEPATH) 335 336 os.chdir(current_path) 337 return build_deps_files_result 338 339 def _execute_build_part_deps_command(self, para): 340 build_part_deps_result = False 341 build_part_deps_command = [] 342 current_path = os.getcwd() 343 # 路径 deps_files_path = ~/OpenHarmony/out/baltimore/deps_files 344 os.chdir(self.project_rootpath) 345 if para.productform == "rk3568": 346 deps_files_path = os.path.abspath(os.path.join( 347 get_build_output_path(para.productform), "deps_files")) 348 else: 349 deps_files_path = os.path.abspath(os.path.join( 350 "out", get_output_path(), "deps_files")) 351 LOG.info("deps_files_path: %s" % deps_files_path) 352 build_part_deps_command.append(self.part_deps_path) 353 build_part_deps_command.append("--deps-files-path") 354 355 if os.path.exists(deps_files_path): 356 build_part_deps_command.append(deps_files_path) 357 LOG.info("build_part_deps_command: %s" % str(build_part_deps_command)) 358 if subprocess.call(build_part_deps_command) == 0: 359 build_part_deps_result = True 360 else: 361 build_part_deps_result = False 362 else: 363 LOG.warning("Build Part Deps Info Error: The %s is not exist" % deps_files_path) 364 365 os.chdir(current_path) 366 return build_part_deps_result 367 368 def _execute_build_xts_command(self, para, xts_build_command): 369 build_result = False 370 current_path = os.getcwd() 371 # eg.路径 acts_rootpath = ~/OpenHarmony/test/xts/acts 372 xts_project_rootpath = os.path.join(sys.source_code_root_path, 373 "test", 374 "xts", 375 para.testtype[0]) 376 os.chdir(self.project_rootpath) 377 if para.productform == "rk3568": 378 os.chdir(xts_project_rootpath) 379 xts_build_command.append(BUILD_PRODUCT_NAME % para.productform) 380 xts_build_command.append("system_size=standard") 381 if len(para.subsystem) > 0: 382 input_subsystem = ",".join(para.subsystem) 383 xts_build_command.append(BUILD_TARGET_SUBSYSTEM % input_subsystem) 384 if para.testsuit != "" and len(para.subsystem) == 0: 385 LOG.error("Please specify subsystem.") 386 return False 387 else: 388 global BUILD_FILEPATH 389 BUILD_FILEPATH = BUILD_FILE_PATH 390 391 if os.path.exists(BUILD_FILEPATH): 392 build_command = [BUILD_FILEPATH] 393 build_command.extend(xts_build_command) 394 LOG.info("build_xts_command: %s" % str(build_command)) 395 if subprocess.call(build_command) == 0: 396 build_result = True 397 else: 398 build_result = False 399 else: 400 LOG.warning("Build XTS Testcase Error: The %s is not exist" % BUILD_FILEPATH) 401 402 os.chdir(current_path) 403 return build_result 404 405############################################################################## 406############################################################################## 407