1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2021 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import sys 17import os 18import argparse 19import shutil 20import xml.etree.ElementTree as ET 21sys.path.append( 22 os.path.dirname(os.path.dirname(os.path.dirname( 23 os.path.abspath(__file__))))) 24from scripts.util.file_utils import read_json_file, write_json_file # noqa: E402 25from scripts.util import build_utils # noqa: E402 26 27 28def copy_dir(src, dest): 29 if not os.path.exists(src): 30 raise Exception("src dir '{}' doesn't exist.".format(src)) 31 if not os.path.exists(dest): 32 os.makedirs(dest, exist_ok=True) 33 result_files = [] 34 src_files = [] 35 for root, _, files in os.walk(src): 36 for _file in files: 37 file_path = os.path.join(root, _file) 38 src_files.append(file_path) 39 for src_path in src_files: 40 if os.path.islink(src_path): 41 continue 42 file_relpath = os.path.relpath(src_path, src) 43 dest_path = os.path.join(dest, file_relpath) 44 dest_dir = os.path.dirname(dest_path) 45 if not os.path.exists(dest_dir): 46 os.makedirs(dest_dir, exist_ok=True) 47 shutil.copy2(src_path, dest_path) 48 result_files.append(src_path) 49 result_files.append(dest_path) 50 return result_files 51 52 53def _resources_with_xml_v1(root, testcase_target_name, test_resource_path, 54 part_build_out_path, resource_output_path): 55 _out_resources_list = [] 56 for target in root: 57 if target.attrib.get('name') != testcase_target_name: 58 continue 59 for _depend in target: 60 _findpath = _depend.attrib.get('findpath') 61 _resource_file = _depend.attrib.get('resource') 62 if _findpath == 'res': 63 _resource_src = os.path.join(test_resource_path, 64 _resource_file) 65 _res_dest = os.path.join(resource_output_path, _resource_file) 66 elif _findpath == 'out': 67 if not os.path.exists(_resource_file): 68 __dir_name = _resource_file.split('/')[0] 69 _resource_file_new = os.path.join(__dir_name, 70 _resource_file) 71 _resource_src_new = os.path.join(part_build_out_path, 72 _resource_file_new) 73 if os.path.exists(_resource_src_new): 74 _resource_src = _resource_src_new 75 _res_dest = os.path.join(resource_output_path, 76 _resource_file) 77 else: 78 _resource_src = '' 79 _res_dest = '' 80 else: 81 _resource_src = os.path.join(part_build_out_path, 82 _resource_file) 83 _res_dest = os.path.join(resource_output_path, 84 _resource_file) 85 else: 86 raise Exception( 87 "resource findpath type '{}' not support.".format( 88 _findpath)) 89 if _resource_src: 90 _out_resources_list.append({ 91 "src": 92 os.path.relpath(_resource_src), 93 "dest": 94 os.path.relpath(_res_dest) 95 }) 96 return _out_resources_list 97 98 99def _parse_res_value(value): 100 res_file = value.split('->')[0].strip() 101 return res_file 102 103 104def _resources_with_xml_v2(root, testcase_target_name, test_resource_path, 105 part_build_out_path, resource_output_path): 106 _out_resources_list = [] 107 for target in root: 108 if target.attrib.get('name') != testcase_target_name: 109 continue 110 for child in target: 111 if child.tag != 'preparer': 112 continue 113 for _option in child: 114 if _option.attrib.get('name') != 'push': 115 continue 116 _src_type = _option.attrib.get('src') 117 _resource_file_val = _option.attrib.get('value') 118 _resource_file = _parse_res_value(_resource_file_val) 119 if _src_type == 'res': 120 _resource_src = os.path.join(test_resource_path, 121 _resource_file) 122 _res_dest = os.path.join(resource_output_path, 123 _resource_file) 124 elif _src_type == 'out': 125 _resource_src = os.path.join(part_build_out_path, 126 _resource_file) 127 _res_dest = os.path.join(resource_output_path, 128 _resource_file) 129 else: 130 raise Exception( 131 "resource src type '{}' not support.".format( 132 _src_type)) 133 if _resource_src: 134 _out_resources_list.append({ 135 "src": 136 os.path.relpath(_resource_src), 137 "dest": 138 os.path.relpath(_res_dest) 139 }) 140 return _out_resources_list 141 142 143def find_testcase_resources(resource_config_file, testcase_target_name, 144 test_resource_path, part_build_out_path, 145 resource_output_path): 146 if not os.path.exists(resource_config_file): 147 return [] 148 tree = ET.parse(resource_config_file) 149 root = tree.getroot() 150 if root.attrib.get('ver') == '2.0': 151 _resources_list = _resources_with_xml_v2(root, testcase_target_name, 152 test_resource_path, 153 part_build_out_path, 154 resource_output_path) 155 else: 156 _resources_list = _resources_with_xml_v1(root, testcase_target_name, 157 test_resource_path, 158 part_build_out_path, 159 resource_output_path) 160 # copy ohos_test.xml 161 _resources_list.append({ 162 "src": 163 resource_config_file, 164 "dest": 165 os.path.join(resource_output_path, 166 os.path.basename(resource_config_file)) 167 }) 168 return _resources_list 169 170 171def copy_testcase_resources(resource_infos): 172 result_dest_list = [] 173 for resource_info in resource_infos: 174 src_file = resource_info.get('src') 175 if not os.path.exists(src_file): 176 print("warning: testcase resource {} doesn't exist.".format( 177 src_file)) 178 return 179 dest_file = resource_info.get('dest') 180 dest_dir = os.path.dirname(dest_file) 181 if os.path.isdir(src_file): 182 result_files = copy_dir(src_file, dest_file) 183 result_dest_list.extend(result_files) 184 else: 185 if not os.path.exists(dest_dir): 186 os.makedirs(dest_dir, exist_ok=True) 187 shutil.copy2(src_file, dest_file) 188 if src_file: 189 result_dest_list.append(src_file) 190 result_dest_list.append(dest_file) 191 return result_dest_list 192 193 194def _get_subsystem_name(part_name): 195 subsystem_parts_file = 'build_configs/parts_info/subsystem_parts.json' 196 subsystem_parts_info = read_json_file(subsystem_parts_file) 197 if subsystem_parts_info is None: 198 raise Exception("read file '{}' failed.".format(subsystem_parts_file)) 199 for name, p_list in subsystem_parts_info.items(): 200 if part_name in p_list: 201 return name 202 return None 203 204 205def _get_subsystem_path(part_name): 206 subsystem_name = _get_subsystem_name(part_name) 207 if subsystem_name is None: 208 return None 209 subsystem_build_config_file = os.path.join('build_configs/subsystem_info', 210 'subsystem_build_config.json') 211 config_info = read_json_file(subsystem_build_config_file) 212 if config_info is None: 213 raise Exception( 214 "read file '{}' failed.".format(subsystem_build_config_file)) 215 subsystem_infos = config_info.get('subsystem') 216 info = subsystem_infos.get(subsystem_name) 217 if info is None: 218 raise Exception( 219 "subsystem '{}' info doesn't exist.".format(subsystem_name)) 220 subsystem_path = info.get('path') 221 return subsystem_path 222 223 224def _parse_module_out_path(module_out_path): 225 split_re = module_out_path.split('/', 1) 226 part_name = split_re[0] 227 module_name = split_re[1] 228 return part_name, module_name 229 230 231def _find_resource_config_file(config_file_name, subsystem_path, module_name): 232 resource_config_file = os.path.join('../../', subsystem_path, 233 'test/resource', module_name, 234 config_file_name) 235 # compatibility 236 if not os.path.exists(resource_config_file): 237 module_dirs = module_name.split('/') 238 _dirs_num = len(module_dirs) 239 _dir_name = os.path.dirname(resource_config_file) 240 while _dirs_num > 1: 241 _dir_name = os.path.dirname(_dir_name) 242 resource_config_file = os.path.join(_dir_name, config_file_name) 243 if os.path.exists(resource_config_file): 244 break 245 _dirs_num -= 1 246 return resource_config_file 247 248 249def _get_res_config_file(module_out_path): 250 part_name, module_name = _parse_module_out_path(module_out_path) 251 subsystem_path = _get_subsystem_path(part_name) 252 if subsystem_path is None: 253 return None 254 resource_config_file = _find_resource_config_file('ohos_test.xml', 255 subsystem_path, 256 module_name) 257 if not os.path.exists(resource_config_file): 258 resource_config_file = _find_resource_config_file( 259 'harmony_test.xml', subsystem_path, module_name) 260 return resource_config_file 261 262 263def main(): 264 parser = argparse.ArgumentParser() 265 parser.add_argument('--resource-config-file', required=False) 266 parser.add_argument('--testcase-target-name', required=True) 267 parser.add_argument('--part-build-out-path', required=True) 268 parser.add_argument('--resource-output-path', required=True) 269 parser.add_argument('--module-out-path', required=False) 270 parser.add_argument('--output-file', required=True) 271 parser.add_argument('--depfile', required=False) 272 args = parser.parse_args() 273 if not args.resource_config_file: 274 if not args.module_out_path: 275 raise Exception('Missing parameter module_out_path.') 276 resource_config_file = _get_res_config_file(args.module_out_path) 277 if resource_config_file is None: 278 print("warning: cannot find resource config file, target: '{}'". 279 format(args.testcase_target_name)) 280 return 0 281 if not os.path.exists(resource_config_file): 282 return 0 283 else: 284 resource_config_file = args.resource_config_file 285 if not os.path.exists(resource_config_file): 286 raise Exception( 287 "testcase '{}' resource_config_file config incorrect.".format( 288 args.testcase_target_name)) 289 290 test_resource_path = os.path.dirname(resource_config_file) 291 resources_list = find_testcase_resources(resource_config_file, 292 args.testcase_target_name, 293 test_resource_path, 294 args.part_build_out_path, 295 args.resource_output_path) 296 write_json_file(args.output_file, resources_list) 297 result_dest_list = copy_testcase_resources(resources_list) 298 if args.depfile and result_dest_list: 299 result_dest_list.sort() 300 build_utils.write_depfile(args.depfile, 301 args.output_file, 302 result_dest_list, 303 add_pydeps=False) 304 return 0 305 306 307if __name__ == '__main__': 308 sys.exit(main()) 309