• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
21
22sys.path.append(
23    os.path.dirname(os.path.dirname(os.path.dirname(
24        os.path.abspath(__file__)))))
25from scripts.util.file_utils import read_json_file, write_json_file  # noqa: E402
26from scripts.util import build_utils  # noqa: E402
27
28
29def copy_dir(src, dest):
30    if not os.path.exists(src):
31        raise Exception("src dir '{}' doesn't exist.".format(src))
32    if not os.path.exists(dest):
33        os.makedirs(dest, exist_ok=True)
34    result_files = []
35    src_files = []
36    for root, _, files in os.walk(src):
37        for _file in files:
38            file_path = os.path.join(root, _file)
39            src_files.append(file_path)
40    for src_path in src_files:
41        if os.path.islink(src_path):
42            continue
43        file_relpath = os.path.relpath(src_path, src)
44        dest_path = os.path.join(dest, file_relpath)
45        dest_dir = os.path.dirname(dest_path)
46        if not os.path.exists(dest_dir):
47            os.makedirs(dest_dir, exist_ok=True)
48        shutil.copy2(src_path, dest_path)
49        result_files.append(src_path)
50        result_files.append(dest_path)
51    return result_files
52
53
54def _resources_with_xml_v1(root, testcase_target_name, test_resource_path,
55                           part_build_out_path, resource_output_path):
56    _out_resources_list = []
57    for target in root:
58        if target.attrib.get('name') != testcase_target_name:
59            continue
60        for _depend in target:
61            _findpath = _depend.attrib.get('findpath')
62            _resource_file = _depend.attrib.get('resource')
63            if _findpath == 'res':
64                _resource_src = os.path.join(test_resource_path,
65                                             _resource_file)
66                _res_dest = os.path.join(resource_output_path, _resource_file)
67            elif _findpath == 'out':
68                if not os.path.exists(_resource_file):
69                    __dir_name = _resource_file.split('/')[0]
70                    _resource_file_new = os.path.join(__dir_name,
71                                                      _resource_file)
72                    _resource_src_new = os.path.join(part_build_out_path,
73                                                     _resource_file_new)
74                    if os.path.exists(_resource_src_new):
75                        _resource_src = _resource_src_new
76                        _res_dest = os.path.join(resource_output_path,
77                                                 _resource_file)
78                    else:
79                        _resource_src = ''
80                        _res_dest = ''
81                else:
82                    _resource_src = os.path.join(part_build_out_path,
83                                                 _resource_file)
84                    _res_dest = os.path.join(resource_output_path,
85                                             _resource_file)
86            else:
87                raise Exception(
88                    "resource findpath type '{}' not support.".format(
89                        _findpath))
90            if _resource_src:
91                _out_resources_list.append({
92                    "src":
93                    os.path.relpath(_resource_src),
94                    "dest":
95                    os.path.relpath(_res_dest)
96                })
97    return _out_resources_list
98
99
100def _parse_res_value(value):
101    res_file = value.split('->')[0].strip()
102    return res_file
103
104
105def _resources_with_xml_v2(root, testcase_target_name, test_resource_path,
106                           part_build_out_path, resource_output_path):
107    _out_resources_list = []
108    for target in root:
109        if target.attrib.get('name') != testcase_target_name:
110            continue
111        for child in target:
112            if child.tag != 'preparer':
113                continue
114            for _option in child:
115                if _option.attrib.get('name') != 'push':
116                    continue
117                _src_type = _option.attrib.get('src')
118                _resource_file_val = _option.attrib.get('value')
119                _resource_file = _parse_res_value(_resource_file_val)
120                if _src_type == 'res':
121                    _resource_src = os.path.join(test_resource_path,
122                                                 _resource_file)
123                    _res_dest = os.path.join(resource_output_path,
124                                             _resource_file)
125                elif _src_type == 'out':
126                    _resource_src = os.path.join(part_build_out_path,
127                                                 _resource_file)
128                    _res_dest = os.path.join(resource_output_path,
129                                             _resource_file)
130                else:
131                    raise Exception(
132                        "resource src type '{}' not support.".format(
133                            _src_type))
134                if _resource_src:
135                    _out_resources_list.append({
136                        "src":
137                        os.path.relpath(_resource_src),
138                        "dest":
139                        os.path.relpath(_res_dest)
140                    })
141    return _out_resources_list
142
143
144def find_testcase_resources(resource_config_file, testcase_target_name,
145                            test_resource_path, part_build_out_path,
146                            resource_output_path):
147    if not os.path.exists(resource_config_file):
148        return []
149    tree = ET.parse(resource_config_file)
150    root = tree.getroot()
151    if root.attrib.get('ver') == '2.0':
152        _resources_list = _resources_with_xml_v2(root, testcase_target_name,
153                                                 test_resource_path,
154                                                 part_build_out_path,
155                                                 resource_output_path)
156    else:
157        _resources_list = _resources_with_xml_v1(root, testcase_target_name,
158                                                 test_resource_path,
159                                                 part_build_out_path,
160                                                 resource_output_path)
161    # copy ohos_test.xml
162    _resources_list.append({
163        "src":
164        resource_config_file,
165        "dest":
166        os.path.join(resource_output_path,
167                     os.path.basename(resource_config_file))
168    })
169    return _resources_list
170
171
172def copy_testcase_resources(resource_infos):
173    result_dest_list = []
174    for resource_info in resource_infos:
175        src_file = resource_info.get('src')
176        if not os.path.exists(src_file):
177            print("warning: testcase resource {} doesn't exist.".format(
178                src_file))
179            return
180        dest_file = resource_info.get('dest')
181        dest_dir = os.path.dirname(dest_file)
182        if os.path.isdir(src_file):
183            result_files = copy_dir(src_file, dest_file)
184            result_dest_list.extend(result_files)
185        else:
186            if not os.path.exists(dest_dir):
187                os.makedirs(dest_dir, exist_ok=True)
188            shutil.copy2(src_file, dest_file)
189            if src_file:
190                result_dest_list.append(src_file)
191                result_dest_list.append(dest_file)
192    return result_dest_list
193
194
195def _get_subsystem_name(part_name):
196    subsystem_parts_file = 'build_configs/parts_info/subsystem_parts.json'
197    subsystem_parts_info = read_json_file(subsystem_parts_file)
198    if subsystem_parts_info is None:
199        raise Exception("read file '{}' failed.".format(subsystem_parts_file))
200    for name, p_list in subsystem_parts_info.items():
201        if part_name in p_list:
202            return name
203    return None
204
205
206def _get_subsystem_path(part_name):
207    subsystem_name = _get_subsystem_name(part_name)
208    if subsystem_name is None:
209        return None
210    subsystem_build_config_file = os.path.join('build_configs/subsystem_info',
211                                               'subsystem_build_config.json')
212    config_info = read_json_file(subsystem_build_config_file)
213    if config_info is None:
214        raise Exception(
215            "read file '{}' failed.".format(subsystem_build_config_file))
216    subsystem_infos = config_info.get('subsystem')
217    info = subsystem_infos.get(subsystem_name)
218    if info is None:
219        raise Exception(
220            "subsystem '{}' info doesn't exist.".format(subsystem_name))
221    subsystem_paths = info.get('path')
222    return subsystem_paths
223
224
225def _parse_module_out_path(module_out_path):
226    split_re = module_out_path.split('/', 1)
227    part_name = split_re[0]
228    module_name = split_re[1]
229    return part_name, module_name
230
231
232def _find_resource_config_file(config_file_name, subsystem_path, module_name):
233    resource_config_file = os.path.join('../../', subsystem_path,
234                                        'test/resource', module_name,
235                                        config_file_name)
236    # compatibility
237    if not os.path.exists(resource_config_file):
238        module_dirs = module_name.split('/')
239        _dirs_num = len(module_dirs)
240        _dir_name = os.path.dirname(resource_config_file)
241        while _dirs_num > 1:
242            _dir_name = os.path.dirname(_dir_name)
243            resource_config_file = os.path.join(_dir_name, config_file_name)
244            if os.path.exists(resource_config_file):
245                break
246            _dirs_num -= 1
247    return resource_config_file
248
249
250def _get_res_config_file(module_out_path):
251    part_name, module_name = _parse_module_out_path(module_out_path)
252    subsystem_paths = _get_subsystem_path(part_name)
253    resource_config_files = []
254    if not subsystem_paths:
255        return resource_config_files
256    for _path in subsystem_paths:
257        resource_config_file = _find_resource_config_file(
258            'ohos_test.xml', _path, module_name)
259        if not os.path.exists(resource_config_file):
260            resource_config_file = _find_resource_config_file(
261                'harmony_test.xml', _path, module_name)
262        resource_config_files.append(resource_config_file)
263    return resource_config_files
264
265
266def _get_resources_list(resource_config_file, testcase_target_name,
267                        part_build_out_path, resource_output_path):
268    if not os.path.exists(resource_config_file):
269        raise Exception(
270            "testcase '{}' resource_config_file config incorrect.".format(
271                testcase_target_name))
272    test_resource_path = os.path.dirname(resource_config_file)
273    resources_list = find_testcase_resources(resource_config_file,
274                                             testcase_target_name,
275                                             test_resource_path,
276                                             part_build_out_path,
277                                             resource_output_path)
278    return resources_list
279
280
281def _get_resources_list_auto_match(module_out_path, testcase_target_name,
282                                   part_build_out_path, resource_output_path):
283    resource_config_files = _get_res_config_file(module_out_path)
284    all_resources_list = []
285    for resource_config_file in resource_config_files:
286        if resource_config_file is None or not os.path.exists(
287                resource_config_file):
288            continue
289        test_resource_path = os.path.dirname(resource_config_file)
290        resources_list = find_testcase_resources(resource_config_file,
291                                                 testcase_target_name,
292                                                 test_resource_path,
293                                                 part_build_out_path,
294                                                 resource_output_path)
295        all_resources_list.extend(resources_list)
296    return all_resources_list
297
298
299def main():
300    parser = argparse.ArgumentParser()
301    parser.add_argument('--resource-config-file', required=False)
302    parser.add_argument('--testcase-target-name', required=True)
303    parser.add_argument('--part-build-out-path', required=True)
304    parser.add_argument('--resource-output-path', required=True)
305    parser.add_argument('--module-out-path', required=False)
306    parser.add_argument('--output-file', required=True)
307    parser.add_argument('--depfile', required=False)
308    args = parser.parse_args()
309    if not args.resource_config_file:
310        if not args.module_out_path:
311            raise Exception('Missing parameter module_out_path.')
312        resources_list = _get_resources_list_auto_match(
313            args.module_out_path, args.testcase_target_name,
314            args.part_build_out_path, args.resource_output_path)
315    else:
316        resources_list = _get_resources_list(args.resource_config_file,
317                                             args.testcase_target_name,
318                                             args.part_build_out_path,
319                                             args.resource_output_path)
320    if not resources_list:
321        return 0
322    write_json_file(args.output_file, resources_list)
323    result_dest_list = copy_testcase_resources(resources_list)
324    if args.depfile and result_dest_list:
325        result_dest_list.sort()
326        build_utils.write_depfile(args.depfile,
327                                  args.output_file,
328                                  result_dest_list,
329                                  add_pydeps=False)
330    return 0
331
332
333if __name__ == '__main__':
334    sys.exit(main())
335