• 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
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