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 write_json_file # noqa: E402
25from scripts.util import build_utils # noqa: E402
26
27
28def copy_dir(src: str, dest: str):
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    src_files = []
34    for root, _, files in os.walk(src):
35        for _file in files:
36            file_path = os.path.join(root, _file)
37            src_files.append(file_path)
38    for src_path in src_files:
39        if os.path.islink(src_path):
40            continue
41        file_relpath = os.path.relpath(src_path, src)
42        dest_path = os.path.join(dest, file_relpath)
43        dest_dir = os.path.dirname(dest_path)
44        if not os.path.exists(dest_dir):
45            os.makedirs(dest_dir, exist_ok=True)
46        shutil.copy2(src_path, dest_path)
47    return 0
48
49
50def _resources_with_xml_v1(root, testcase_target_name: str, test_resource_path: str,
51                           part_build_out_path: str, resource_output_path: str):
52    _out_resources_list = []
53    for target in root:
54        if target.attrib.get('name') != testcase_target_name:
55            continue
56        for _depend in target:
57            _findpath = _depend.attrib.get('findpath')
58            _resource_file = _depend.attrib.get('resource')
59            if _findpath == 'res':
60                _resource_src = os.path.join(test_resource_path,
61                                             _resource_file)
62                _res_dest = os.path.join(resource_output_path, _resource_file)
63            elif _findpath == 'out':
64                if not os.path.exists(_resource_file):
65                    __dir_name = _resource_file.split('/')[0]
66                    _resource_file_new = os.path.join(__dir_name,
67                                                      _resource_file)
68                    _resource_src_new = os.path.join(part_build_out_path,
69                                                     _resource_file_new)
70                    if os.path.exists(_resource_src_new):
71                        _resource_src = _resource_src_new
72                        _res_dest = os.path.join(resource_output_path,
73                                                 _resource_file)
74                    else:
75                        _resource_src = ''
76                        _res_dest = ''
77                else:
78                    _resource_src = os.path.join(part_build_out_path,
79                                                 _resource_file)
80                    _res_dest = os.path.join(resource_output_path,
81                                             _resource_file)
82            else:
83                raise Exception(
84                    "resource findpath type '{}' not support.".format(
85                        _findpath))
86            if _resource_src:
87                _out_resources_list.append({
88                    "src":
89                    os.path.relpath(_resource_src),
90                    "dest":
91                    os.path.relpath(_res_dest)
92                })
93    return _out_resources_list
94
95
96def _parse_res_value(value: str):
97    res_file = value.split('->')[0].strip()
98    return res_file
99
100
101def _resources_with_xml_v2(root, testcase_target_name: str, test_resource_path: str,
102                           part_build_out_path: str, resource_output_path: str):
103    _out_resources_list = []
104    for target in root:
105        if target.attrib.get('name') != testcase_target_name:
106            continue
107        for child in target:
108            if child.tag != 'preparer':
109                continue
110            for _option in child:
111                if _option.attrib.get('name') != 'push':
112                    continue
113                _src_type = _option.attrib.get('src')
114                _resource_file_val = _option.attrib.get('value')
115                _resource_file = _parse_res_value(_resource_file_val)
116                if _src_type == 'res':
117                    _resource_src = os.path.join(test_resource_path,
118                                                 _resource_file)
119                    _res_dest = os.path.join(resource_output_path,
120                                             _resource_file)
121                elif _src_type == 'out':
122                    _resource_src = os.path.join(part_build_out_path,
123                                                 _resource_file)
124                    _res_dest = os.path.join(resource_output_path,
125                                             _resource_file)
126                else:
127                    raise Exception(
128                        "resource src type '{}' not support.".format(
129                            _src_type))
130                if _resource_src:
131                    _out_resources_list.append({
132                        "src":
133                        os.path.relpath(_resource_src),
134                        "dest":
135                        os.path.relpath(_res_dest)
136                    })
137    return _out_resources_list
138
139
140def find_testcase_resources(resource_config_file: str, testcase_target_name: str,
141                            test_resource_path: str, part_build_out_path: str,
142                            resource_output_path: str):
143    if not os.path.exists(resource_config_file):
144        return []
145    tree = ET.parse(resource_config_file)
146    root = tree.getroot()
147    if root.attrib.get('ver') == '2.0':
148        _resources_list = _resources_with_xml_v2(root, testcase_target_name,
149                                                 test_resource_path,
150                                                 part_build_out_path,
151                                                 resource_output_path)
152    else:
153        _resources_list = _resources_with_xml_v1(root, testcase_target_name,
154                                                 test_resource_path,
155                                                 part_build_out_path,
156                                                 resource_output_path)
157    # copy ohos_test.xml
158    _resources_list.append({
159        "src":
160        resource_config_file,
161        "dest":
162        os.path.join(resource_output_path,
163                     os.path.basename(resource_config_file))
164    })
165    return _resources_list
166
167
168def copy_testcase_resources(resource_infos: dict):
169    for resource_info in resource_infos:
170        src_file = resource_info.get('src')
171        if not os.path.exists(src_file):
172            print("warning: testcase resource {} doesn't exist.".format(
173                src_file))
174            return 0
175        dest_file = resource_info.get('dest')
176        dest_dir = os.path.dirname(dest_file)
177        if os.path.isdir(src_file):
178            copy_dir(src_file, dest_file)
179        else:
180            if not os.path.exists(dest_dir):
181                os.makedirs(dest_dir, exist_ok=True)
182            shutil.copy2(src_file, dest_file)
183    return 0
184
185
186def main():
187    parser = argparse.ArgumentParser()
188    parser.add_argument('--resource-config-file', required=False)
189    parser.add_argument('--testcase-target-name', required=True)
190    parser.add_argument('--part-build-out-path', required=True)
191    parser.add_argument('--resource-output-path', required=True)
192    parser.add_argument('--output-file', required=True)
193    args = parser.parse_args()
194    if not args.resource_config_file:
195        return 0
196    else:
197        resource_config_file = args.resource_config_file
198        if not os.path.exists(resource_config_file):
199            raise Exception(
200                "testcase '{}' resource_config_file config incorrect.".format(
201                    args.testcase_target_name))
202
203    test_resource_path = os.path.dirname(resource_config_file)
204    resources_list = find_testcase_resources(resource_config_file,
205                                             args.testcase_target_name,
206                                             test_resource_path,
207                                             args.part_build_out_path,
208                                             args.resource_output_path)
209    write_json_file(args.output_file, resources_list)
210    copy_testcase_resources(resources_list)
211    return 0
212
213
214if __name__ == '__main__':
215    sys.exit(main())
216