1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3""" 4Copyright (c) 2021 Huawei Device Co., Ltd. 5Licensed under the Apache License, Version 2.0 (the "License"); 6you may not use this file except in compliance with the License. 7You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11Unless required by applicable law or agreed to in writing, software 12distributed under the License is distributed on an "AS IS" BASIS, 13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14See the License for the specific language governing permissions and 15limitations under the License. 16""" 17 18import os 19import fnmatch 20import sys 21import argparse 22import json 23import platform 24import subprocess 25 26import distutils.dir_util as dir_util 27import distutils.file_util as file_util 28from distutils.errors import DistutilsError 29from string import Template 30 31# all sub system list, must be lowercase. 32_SUB_SYSTEM_LIST = [ 33 "kernel", 34 "hiviewdfx", 35 "communication", 36 "security", 37 "update", 38 "sstsutils", 39 "commonlibrary", 40 "multimedia", 41 "hdf", 42 "ability", 43 "appexecfwk", 44 "distributed_schedule", 45 "startup", 46 "sensors", 47 "sample", 48 "iothardware", 49 "open_posix_testsuite", 50 "graphic", 51 "ace", 52 "applications", 53 "ai", 54 "global", 55 "telephony", 56 "dcts", 57 "distributeddatamgr", 58 "xts" 59] 60 61_NO_FILTE_SUB_SYSTEM_LIST = [ 62 "appexecfwk", 63 "applications", 64 "kernel", 65 "open_posix_testsuite", 66 "sample", 67 "telephony", 68 "dcts", 69 "hiviewdfx", 70 "security", 71 "update", 72 "sstsutils", 73 "hdf", 74 "distributed_schedule", 75 "xts", 76 "commonlibrary", 77 "communication", 78 "distributeddatamgr", 79 "startup" 80] 81 82 83def main(): 84 parser = argparse.ArgumentParser() 85 parser.add_argument('--method_name', help='', required=True) 86 parser.add_argument('--arguments', help='', 87 required=True) # format key=value#key=value 88 args = parser.parse_args() 89 this_module = sys.modules[__name__] 90 method = getattr(this_module, args.method_name) 91 arguments = {} 92 for argument in args.arguments.split("#"): 93 key_value = argument.strip().split("=") 94 if len(key_value) != 2: 95 raise ValueError( 96 "The arguments' format is 'key=value#key=value'. Wrong format:" 97 " {}".format(argument)) 98 arguments.setdefault(key_value[0].strip(), key_value[1].strip()) 99 method(**arguments) 100 return 0 101 102 103def read_file(input_file): 104 if not os.path.exists(input_file): 105 return "" 106 107 with open(input_file, 'r') as input_f: 108 content = input_f.read().strip() 109 return content 110 111 112def write_file(output_file, content, append): 113 file_dir = os.path.dirname(os.path.abspath(output_file)) 114 if not os.path.exists(file_dir): 115 os.makedirs(file_dir) 116 mode = 'a+' if append else 'w' 117 with open(output_file, mode) as output_f: 118 output_f.write("%s\n" % content) 119 120 121def copy_file(output, sources="", source_dirs="", to_dir=True): 122 """ 123 copy source files or source dir to output. 124 if sources is not empty, the output can be file(will be created 125 automatically) 126 or directory(must be exist). 127 :param output: If source_dirs is not empty, output must be directory. 128 :param sources: source files is separated by dot 129 :param source_dirs: source directory is separated by dot 130 :param to_dir: output is directory or not 131 :return: 132 """ 133 if not sources and not source_dirs: 134 raise Exception( 135 "sources or source_dirs parameter must be specified one") 136 _output = output.strip() 137 _sources = sources.strip() 138 _source_dirs = source_dirs.strip() 139 _parent_output = os.path.dirname(_output) 140 try: 141 if to_dir and not os.path.exists(_output): 142 os.makedirs(_output) 143 if not to_dir and not os.path.exists(_parent_output): 144 os.makedirs(_parent_output) 145 except OSError: 146 if not os.path.isdir(_output): 147 raise 148 try: 149 if _sources: 150 _copy_files(_sources.split(","), _output) 151 152 if _source_dirs: 153 _copy_dir(_source_dirs.split(","), _output) 154 except DistutilsError: 155 print("ignore file exist error") 156 return 0 157 158 159def _copy_files(sources, output): 160 copy_set = set() 161 for source_file in sources: 162 source_file = source_file.strip() 163 if os.path.isfile(source_file) and os.path.exists(source_file): 164 # if same file name exist, add dir path 165 if os.path.basename(source_file) in copy_set: 166 new_output = os.path.join(output, os.path.dirname(source_file). 167 split(os.sep)[-1]) 168 if not os.path.exists(new_output): 169 os.makedirs(new_output) 170 file_util.copy_file(source_file, new_output) 171 else: 172 file_util.copy_file(source_file, output) 173 copy_set.add(os.path.basename(source_file)) 174 175 176def _copy_dir(sources, output): 177 for source_file in sources: 178 source_file = source_file.strip() 179 if os.path.isdir(source_file): 180 dir_util.copy_tree(source_file, output) 181 182 183def gen_suite_out(suite_output_prefix, suite_names, out_suffix): 184 outputs = [] 185 _suite_output_prefix = suite_output_prefix.strip() 186 _dirname_suffix = out_suffix.strip().rstrip(os.sep) 187 for suite in suite_names.split(","): 188 path = "%s%s/%s" % ( 189 _suite_output_prefix, suite.strip(), _dirname_suffix) 190 outputs.append(path) 191 print(path) 192 return outputs 193 194 195def get_subsystem_name(path): 196 subsystem_name = "" 197 for subsystem in _SUB_SYSTEM_LIST: 198 subsystem_path = "/{}/".format(subsystem) 199 _path = path.lower() 200 if subsystem_path in _path: 201 subsystem_name = subsystem 202 break 203 subsystem_path = "/{}_lite/".format(subsystem) 204 if subsystem_path in _path: 205 subsystem_name = subsystem 206 break 207 sys.stdout.write(subsystem_name) 208 return subsystem_name 209 210 211def get_modulename_by_buildtarget(module_list_file, build_target): 212 if not os.path.exists(module_list_file): 213 return "" 214 with open(module_list_file, "r") as module_file: 215 module_info_data = json.load(module_file) 216 for module in module_info_data: 217 if module_info_data[module]["build_target_name"] == build_target: 218 sys.stdout.write(module) 219 return module 220 return "" 221 222 223def glob(path, filename_pattern): 224 files = [] 225 for dir_path, _, files in os.walk(path): 226 for filename in fnmatch.filter(files, filename_pattern): 227 files.append(os.path.join(dir_path, filename)) 228 return files 229 230 231def filter_by_subsystem(testsuites, product_json): 232 product_info = {} 233 filtered_features = [] 234 subs_comps = {} 235 # parses product json to obtain all the subsystem name 236 if os.path.exists(product_json): 237 try: 238 with open(product_json, 'r') as product_info: 239 product_info = json.load(product_info) 240 except ValueError: 241 print("NO json object could be decoded.") 242 subsystem_info = product_info.get("subsystems") 243 for subsystem in subsystem_info: 244 subs_comps[subsystem.get("subsystem")] = \ 245 subsystem.get("components", []) 246 247 feature_list = testsuites.split(",") 248 for feature in feature_list: 249 # if subsytem name match 250 subsystem = get_subsystem_name_no_output(feature) 251 if subsystem in _NO_FILTE_SUB_SYSTEM_LIST: 252 filtered_features.append(feature) 253 print(feature) 254 elif subsystem in subs_comps: 255 components = subs_comps.get(subsystem, []) 256 if check_component(feature, components): 257 filtered_features.append(feature) 258 print(feature) 259 return filtered_features 260 261 262def get_subsystem_name_no_output(path): 263 subsystem_name = "" 264 for subsystem in _SUB_SYSTEM_LIST: 265 subsystem_path = "/{}".format(subsystem) 266 _path = path.lower() 267 if subsystem_path in _path: 268 subsystem_name = subsystem 269 break 270 subsystem_path = "/{}_lite".format(subsystem) 271 if subsystem_path in _path: 272 subsystem_name = subsystem 273 break 274 return subsystem_name 275 276 277def check_component(path, components): 278 for component in components: 279 component_name = component.get("component", "") 280 if component_name != "kv_store_lite": 281 component_name = component_name.split('_lite')[0] 282 if component_name in path or "{}_hal".format(component_name) in path \ 283 or "{}_posix".format(component_name) in path: 284 return True 285 return False 286 287 288def get_python_cmd(): 289 major, _, _ = platform.python_version_tuple() 290 if major == "3": 291 return "python" 292 else: 293 return "python3" 294 295 296def record_testmodule_info(build_target_name, module_name, 297 subsystem_name, suite_out_dir, same_file=False): 298 if not build_target_name or not subsystem_name: 299 print( 300 'build_target_name or subsystem_name of testmodule "%s" ' 301 'is invalid!' % module_name) 302 return 303 if same_file: 304 module_info_list_file = os.path.join(suite_out_dir, 'module_info.json') 305 else: 306 module_info_list_file = os.path.join(suite_out_dir, 307 '{}_module_info.json'.format 308 (build_target_name)) 309 module_info_data = {} 310 if os.path.exists(module_info_list_file): 311 try: 312 with open(module_info_list_file, 'r') as module_file: 313 module_info_data = json.load(module_file) 314 except ValueError: 315 print("NO json object could be decoded but continue") 316 module_info = {'subsystem': subsystem_name, 317 'build_target_name': build_target_name} 318 module_info_data[module_name] = module_info 319 with open(module_info_list_file, 'w') as out_file: 320 json.dump(module_info_data, out_file) 321 322 323def record_test_component_info(out_dir, version): 324 if not os.path.exists(out_dir): 325 os.makedirs(out_dir) 326 all_module_file = os.path.join(out_dir, 'module_info.json') 327 all_module_data = {} 328 for root, dirs, files in os.walk(out_dir): 329 for file in files: 330 if file.endswith("module_info.json"): 331 with open(os.path.join(root, file), 'r') as json_data: 332 module_data = json.load(json_data) 333 all_module_data.update(module_data) 334 os.remove(os.path.join(root, file)) 335 with open(all_module_file, 'w') as out_file: 336 json.dump(all_module_data, out_file) 337 338 test_component_file = os.path.join(out_dir, 'test_component.json') 339 test_component_data = {'version': version, } 340 with open(test_component_file, 'w') as out_file: 341 json.dump(test_component_data, out_file) 342 343 344def get_target_modules(all_features): 345 feature_list = [] 346 if all_features: 347 for feature in all_features.split(","): 348 if feature: 349 feature_list.append(feature) 350 print(feature) 351 return feature_list 352 353 354def cmd_popen(cmd): 355 proc = subprocess.Popen(cmd) 356 proc.wait() 357 ret_code = proc.returncode 358 if ret_code != 0: 359 raise Exception("{} failed, return code is {}".format(cmd, ret_code)) 360 361 362def build_js_hap(project_path, out_put_dir, hap_name): 363 if not check_env(): 364 return 365 gradle_dir = os.path.join(project_path, "gradle") 366 os.chdir(gradle_dir) 367 build_clean = ["gradle", "clean"] 368 cmd_popen(build_clean) 369 build_cmd = ["gradle", "entry:packageDebugHap"] 370 cmd_popen(build_cmd) 371 gralde_output_dir = os.path.join(gradle_dir, "entry", "build", "outputs") 372 if os.path.exists(gralde_output_dir): 373 for root, _, files in os.walk(gralde_output_dir): 374 for file in files: 375 if file.endswith(".hap"): 376 file_util.copy_file(os.path.join(root, file), 377 os.path.join(out_put_dir.rstrip(','), 378 hap_name)) 379 return 380 381 382 383def check_env(): 384 """ 385 check all the env for js hap build 386 return: return true if all env ready, otherwise return false 387 """ 388 env_list = ['OHOS_SDK_HOME', 'NODE_HOME', 'GRADLE_HOME'] 389 for env in env_list: 390 if not os.environ.get(env): 391 print("the env {} not set, skip build!".format(env)) 392 return False 393 else: 394 return True 395 396 397def generate_allinone_testjson_by_template(tmpl_file, module_name, product_name, config_file): 398 if not os.path.exists(tmpl_file): 399 raise Exception( 400 "Can't find the Test.json or Test.tmpl in the " 401 "path %s " % os.path.dirname( 402 test_xml)) 403 tmpl_content = read_file(tmpl_file) 404 values = {"module": module_name, "product": product_name} 405 xml_content = Template(tmpl_content).substitute(values) 406 write_file(config_file, xml_content, False) 407 408 409if __name__ == '__main__': 410 sys.exit(main()) 411