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 scan_support_product 29from core.common import is_open_source_product 30from core.config.config_manager import UserConfigManager 31 32BUILD_FILEPATH = "./build.sh" 33BUILD_LITE = "build/lite/build.py" 34BUILD_TARGET_PLATFORM = "build_platform=\"%s\"" 35BUILD_PRODUCT_NAME = "product_name=%s" 36BUILD_TARGET_SUBSYSTEM = "target_subsystem=%s" 37BUILD_TARGET_SUITE = "suite=%s" 38LOG = platform_logger("BuildTestcases") 39 40 41############################################################################## 42############################################################################## 43 44class BuildTestcases(object): 45 def __init__(self, project_rootpath): 46 self.project_rootpath = project_rootpath 47 self.xts_project_rootpath = os.path.join(sys.source_code_root_path, 48 "test", 49 "xts", 50 "acts") 51 user_manager = UserConfigManager() 52 self.is_build_example = user_manager.get_user_config_flag( 53 "build", "example") 54 self.build_parameter_dic = user_manager.get_user_config( 55 "build", "parameter") 56 57 @classmethod 58 def _copy_folder(cls, source_dir, target_dir): 59 if not os.path.exists(target_dir): 60 os.makedirs(target_dir) 61 62 if platform.system() == 'Windows': 63 command = ["xcopy", "/f", "/s", "/e", "/y", 64 "/b", "/q", source_dir, target_dir] 65 else: 66 command = ["cp", "-rf", source_dir, target_dir] 67 68 LOG.info("command: %s" % str(command)) 69 return subprocess.call(command) == 0 70 71 @classmethod 72 def _get_testcase_outname_by_productform(cls, productform): 73 if productform == "phone" or is_open_source_product(productform): 74 return "" 75 76 testcase_outpath = "" 77 78 # 路径注释 get_build_output_path = OpenHarmony/out/rk3568/build_configs/platforms_info/toolchain_to_variant.json 79 toolchain_filepath = os.path.join( 80 get_build_output_path(productform), 81 "build_configs", 82 "platforms_info", 83 "toolchain_to_variant.json") 84 if os.path.exists(toolchain_filepath): 85 data_dic = [] 86 with open(toolchain_filepath, 'r') as toolchain_file: 87 data_dic = json.load(toolchain_file) 88 if not data_dic: 89 LOG.warning("The %s file load error." % 90 toolchain_filepath) 91 data_dic = [] 92 paltform_toolchain_dic = data_dic.get("platform_toolchain") 93 testcase_outpath = paltform_toolchain_dic.get(productform, "") 94 pos = testcase_outpath.rfind(':') + 1 95 testcase_outpath = testcase_outpath[pos:len(testcase_outpath)] 96 return testcase_outpath 97 98 @classmethod 99 def _delete_acts_testcase_dir(cls, productform): 100 acts_testcase_out_dir = os.path.join( 101 get_build_output_path(productform), 102 "suites", 103 "acts", 104 "testcases") 105 LOG.info("acts_testcase_out_dir=%s" % acts_testcase_out_dir) 106 # 删除~/OpenHarmony/out/rk3568/suites/acts/testcases目录内容 107 if os.path.exists(acts_testcase_out_dir): 108 shutil.rmtree(acts_testcase_out_dir) 109 110 def _delete_testcase_dir(self, productform): 111 if is_open_source_product(productform): 112 package_out_dir = os.path.join( 113 get_build_output_path(productform), 114 "packages", 115 "phone", 116 "tests") 117 else: 118 package_out_dir = os.path.join( 119 get_build_output_path(productform), 120 "packages", 121 productform, 122 "tests") 123 124 LOG.info("package_out_dir=%s" % package_out_dir) 125 # 删除~/OpenHarmony/out/rk3568/packages/phone/tests目录内容 126 if os.path.exists(package_out_dir): 127 shutil.rmtree(package_out_dir) 128 129 phone_out_dir = os.path.join( 130 self.project_rootpath, "out", "release", "tests") 131 LOG.info("phone_out_dir=%s" % phone_out_dir) 132 # 删除~/OpenHarmony/out/release/tests目录内容 133 if os.path.exists(phone_out_dir): 134 shutil.rmtree(phone_out_dir) 135 136 curr_productform_outname = self._get_testcase_outname_by_productform( 137 productform) 138 if curr_productform_outname == "": 139 return 140 141 curr_productform_outdir = os.path.join( 142 get_build_output_path(productform), 143 curr_productform_outname, 144 "tests") 145 LOG.info("curr_productform_outdir=%s" % curr_productform_outdir) 146 if os.path.exists(curr_productform_outdir): 147 shutil.rmtree(curr_productform_outdir) 148 149 def _merge_testcase_dir(self, productform): 150 if is_open_source_product(productform): 151 package_out_dir = os.path.join( 152 get_build_output_path(productform), 153 "packages", 154 "phone") 155 else: 156 package_out_dir = os.path.join( 157 get_build_output_path(productform), 158 "packages", 159 productform) 160 if platform.system() == 'Windows': 161 package_out_dir = os.path.join(package_out_dir, "tests") 162 163 phone_out_dir = os.path.join(get_build_output_path(productform), 164 "tests") 165 if os.path.exists(phone_out_dir): 166 self._copy_folder(phone_out_dir, package_out_dir) 167 168 curr_productform_outname = self._get_testcase_outname_by_productform( 169 productform) 170 if curr_productform_outname == "": 171 return 172 173 curr_productform_outdir = os.path.join( 174 get_build_output_path(productform), 175 curr_productform_outname, 176 "tests") 177 LOG.info("curr_productform_outdir=%s" % curr_productform_outdir) 178 if os.path.exists(curr_productform_outdir): 179 self._copy_folder(curr_productform_outdir, package_out_dir) 180 181 def _execute_build_command(self, productform, command): 182 build_result = False 183 current_path = os.getcwd() 184 os.chdir(self.project_rootpath) 185 186 command.append("--product-name") 187 command.append(productform) 188 189 if os.path.exists(BUILD_FILEPATH): 190 build_command = [BUILD_FILEPATH] 191 build_command.extend(command) 192 LOG.info("build_command: %s" % str(build_command)) 193 if subprocess.call(build_command) == 0: 194 build_result = True 195 else: 196 build_result = False 197 else: 198 LOG.warning("Error: The %s is not exist" % BUILD_FILEPATH) 199 200 os.chdir(current_path) 201 return build_result 202 203 def _execute_build_acts_command(self, para): 204 build_result = False 205 acts_build_command = [] 206 current_path = os.getcwd() 207 # 路径 acts_rootpath = ~/OpenHarmony/test/xts/acts 208 os.chdir(self.xts_project_rootpath) 209 acts_build_command.append(BUILD_PRODUCT_NAME % para.productform) 210 acts_build_command.append("system_size=standard") 211 if len(para.subsystem) > 0: 212 input_subsystem = ",".join(para.subsystem) 213 acts_build_command.append(BUILD_TARGET_SUBSYSTEM % input_subsystem) 214 if para.testsuit != "" and len(para.subsystem) == 0: 215 LOG.error("Please specify subsystem.") 216 return 217 target_cpu = self.build_parameter_dic.get("target_cpu") 218 if target_cpu == "arm64": 219 acts_build_command.append("target_arch=" + target_cpu) 220 if os.path.exists(BUILD_FILEPATH): 221 build_command = [BUILD_FILEPATH] 222 build_command.extend(acts_build_command) 223 LOG.info("build_acts_command: %s" % str(build_command)) 224 if subprocess.call(build_command) == 0: 225 build_result = True 226 else: 227 build_result = False 228 else: 229 LOG.warning("Build Acts Testcase Error: The %s is not exist" % BUILD_FILEPATH) 230 231 os.chdir(current_path) 232 return build_result 233 234 def build_fuzz_testcases(self, para): 235 self._delete_testcase_dir(para.productform) 236 helper_path = os.path.join("..", "libs", "fuzzlib", "fuzzer_helper.py") 237 command = [sys.executable, helper_path, 'make', 238 'make_temp_test', para.productform] 239 if subprocess.call(command, shell=False) == 0: 240 build_result = True 241 else: 242 build_result = False 243 self._merge_testcase_dir(para.productform) 244 return build_result 245 246 # 编译测试用例(编译命令拼接) 247 def build_testcases(self, productform, target): 248 command = [] 249 if self.is_build_example: 250 command.append("--gn-args") 251 command.append("build_example=true") 252 command.append("--build-target") 253 command.append(target) 254 target_cpu = self.build_parameter_dic.get("target_cpu") 255 if target_cpu == "arm64": 256 if productform == "m40": 257 command.append("--gn-args") 258 command.append("use_musl=false") 259 command.append("--gn-args") 260 command.append("use_custom_libcxx=true") 261 command.append("--gn-args") 262 command.append("use_custom_clang=true") 263 command.append("--target-cpu") 264 command.append(target_cpu) 265 command.append("--ccache") 266 self._delete_testcase_dir(productform) 267 build_result = self._execute_build_command(productform, command) 268 self._merge_testcase_dir(productform) 269 return build_result 270 271 # 编译ACTS测试用例 272 def build_acts_testcases(self, para): 273 self._delete_acts_testcase_dir(para.productform) 274 build_result = self._execute_build_acts_command(para) 275 return build_result 276 277 def build_gn_file(self, productform): 278 command = [] 279 if self.is_build_example: 280 command.append("--gn-args") 281 command.append("build_example=true") 282 command.append("--build-only-gn") 283 command.append("--gn-args") 284 command.append(BUILD_TARGET_PLATFORM % productform) 285 return self._execute_build_command(productform, command) 286 287 def build_version(self, productform): 288 command = [] 289 command.append("--build-target") 290 command.append("make_all") 291 command.append("--gn-args") 292 command.append(BUILD_TARGET_PLATFORM % productform) 293 return self._execute_build_command(productform, command) 294 295 296############################################################################## 297############################################################################## 298