• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# coding: utf-8
3#
4# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without modification,
7# are permitted provided that the following conditions are met:
8#
9# 1. Redistributions of source code must retain the above copyright notice, this list of
10#    conditions and the following disclaimer.
11#
12# 2. Redistributions in binary form must reproduce the above copyright notice, this list
13#    of conditions and the following disclaimer in the documentation and/or other materials
14#    provided with the distribution.
15#
16# 3. Neither the name of the copyright holder nor the names of its contributors may be used
17#    to endorse or promote products derived from this software without specific prior written
18#    permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
24# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32import os
33import platform
34import shutil
35import subprocess
36import sys
37import base64
38
39SOURCE_ROOT = "../../"
40CMAKE_GEN_PATH = "cmake-build-debug/"
41WORK_DIR = ""
42ERROR_COLOR_PREFIX = "\033[31m"
43ERROR_COLOR_END = "\033[0m"
44ALIGNED_PARM = ''
45
46
47def setup_hcgen_compiler():
48    global SOURCE_ROOT
49    global CMAKE_GEN_PATH
50
51    if len(sys.argv) > 1:
52        hcgen_path = os.path.abspath(sys.argv[1])
53        if hcgen_path.find('hc-gen') >= 0 and os.access(hcgen_path, os.X_OK):
54            print('use specified hsc:' + hcgen_path)
55            return hcgen_path
56
57    source_root = '../../'
58    compiler_name = "hc-gen"
59    if platform.system() == "Windows":
60        source_root = source_root.replace("/", "\\")
61        compiler_name += ".exe"
62
63    source_root = os.path.abspath(os.path.join(WORK_DIR, source_root))
64    hcgen_path = os.path.join(source_root, compiler_name)
65    if not os.access(hcgen_path, os.X_OK):
66        hcgen_path = os.path.join(source_root, CMAKE_GEN_PATH, compiler_name)
67        if not os.access(hcgen_path, os.X_OK):
68            print("Error: hcgen not found, please make first")
69            exit(1)
70
71    return hcgen_path
72
73
74def index_case(case_path):
75    cases = []
76    for directory in os.listdir(case_path):
77        if os.path.isdir(os.path.join(case_path, directory)):
78            cases.append(directory)
79    cases.sort()
80    return cases
81
82
83def save_compile_result(mode, case_name, status, output):
84    result_file_name = os.path.join(WORK_DIR, case_name,
85                                    'golden_%s_compile_result.txt' % mode)
86    with open(result_file_name, 'w') as result_output:
87        status_str = "[compile exit status]:" + str(status)
88        output_str = "\n[compile console output]:\n" + output
89        result_output.write(status_str)
90        result_output.write(output_str)
91
92
93def gen_decompile_golden(hcgen_path, case_name):
94    source_file = os.path.join(WORK_DIR, case_name, 'golden.hcb')
95    target_file = os.path.join(WORK_DIR, case_name, 'golden')
96    command = "%s -o %s -d %s" % (hcgen_path, target_file, source_file)
97    status, output = subprocess.getstatusoutput(command)
98    if status:
99        print('case %s decompile fail:\n %s, status=%d' %
100              (case_name, output, status))
101
102    return status == 0
103
104
105def recode_hcb_file(file_path):
106    with open(file_path, 'rb') as hcb_file:
107        content = hcb_file.read()
108        hcb_file.close()
109
110    with open(file_path, 'wb') as hcb_file:
111        base64_content = base64.b64encode(content)
112        hcb_file.write(base64_content)
113        hcb_file.close()
114
115
116def build_binary(hcgen_path, case_name):
117    source_file = os.path.join(WORK_DIR, case_name, 'case.hcs')
118    target_file = os.path.join(WORK_DIR, case_name, 'golden')
119    command = "%s %s -o %s %s" % \
120              (hcgen_path, ALIGNED_PARM, target_file, source_file)
121    status, output = subprocess.getstatusoutput(command)
122    if case_name.endswith('_ei'):
123        if status == 0:
124            print("CASE_ERROR:error identify case " + case_name
125                  + "expect build fail but success at binary mode")
126            return False
127    elif status != 0:
128        print("CASE_ERROR:case " + case_name
129              + " expect build success but failed at binary mode")
130        return False
131    output = output.replace(WORK_DIR, ".").replace('\\', '/') \
132        .replace(ERROR_COLOR_PREFIX, "") \
133        .replace(ERROR_COLOR_END, "").strip()
134
135    save_compile_result('binary', case_name, status, output)
136
137    result = True
138    if status == 0:
139        result = gen_decompile_golden(hcgen_path, case_name)
140        if result:
141            recode_hcb_file(target_file + '.hcb')
142    return result
143
144
145def build_text(hcgen_path, case_name):
146    source_file = os.path.join(WORK_DIR, case_name, 'case.hcs')
147    target_file = os.path.join(WORK_DIR, case_name, 'golden')
148    command = "%s -t -o %s %s" % (hcgen_path, target_file, source_file)
149    status, output = subprocess.getstatusoutput(command)
150    if case_name.endswith('_ei') or case_name.find('node_duplicate_name') >= 0:
151        if status == 0:
152            print("CASE_ERROR:error identify case "
153                  + case_name + " expect build fail but success at text mode")
154            print(output)
155            return False
156    elif status != 0:
157        print("CASE_ERROR:case " + case_name
158              + " expect build success but failed at text mode")
159        print(output)
160        return False
161    output = output.replace(WORK_DIR, ".").replace('\\', '/') \
162        .replace(ERROR_COLOR_PREFIX, "") \
163        .replace(ERROR_COLOR_END, "").strip()
164
165    save_compile_result('text', case_name, status, output)
166
167    if status == 0:
168        os.rename(target_file + '.c', target_file + '.c.gen')
169        os.rename(target_file + '.h', target_file + '.h.gen')
170    return True
171
172
173def build_macro(hcgen_path, case_name):
174    source_file = os.path.join(WORK_DIR, case_name, 'case.hcs')
175    target_file = os.path.join(WORK_DIR, case_name, 'macro')
176    command = "%s -m -o %s %s" % (hcgen_path, target_file, source_file)
177    status, output = subprocess.getstatusoutput(command)
178    if case_name.endswith('_ei'):
179        if status == 0:
180            print("CASE_ERROR:error identify case "
181                  + case_name + " expect build fail but success at macro mode")
182            print(output)
183            return False
184    elif status != 0:
185        print("CASE_ERROR:case " + case_name
186              + " expect build success but failed at macro mode")
187        print(output)
188        return False
189    output = output.replace(WORK_DIR, ".").replace('\\', '/') \
190        .replace(ERROR_COLOR_PREFIX, "") \
191        .replace(ERROR_COLOR_END, "").strip()
192
193    save_compile_result('macro', case_name, status, output)
194
195    if status == 0:
196        os.rename(target_file + '.h', target_file + '.h.gen')
197    return True
198
199
200def build_cases(hcgen_path, cases):
201    index = 1
202    failed_cases = []
203    for case in cases:
204        print('[%02d/%d] build %s' % (index, len(cases), case))
205        text_compile = build_text(hcgen_path, case)
206        binary_compile = build_binary(hcgen_path, case)
207        macro_compile = build_macro(hcgen_path, case)
208        if not text_compile or not binary_compile or not macro_compile:
209            failed_cases.append(case)
210        index += 1
211
212    print("\nUpdate cases result :\ntotal case: %d, failed: %d, success: %d" %
213          (len(cases), len(failed_cases), len(cases) - len(failed_cases)))
214    if len(failed_cases) > 0:
215        print("Failed case as below:")
216        for case in failed_cases:
217            print(case)
218
219
220def setup_work_dir():
221    global WORK_DIR
222    pwd = os.path.abspath(sys.argv[0])
223    pwd = pwd[:pwd.rfind(os.sep)]
224    WORK_DIR = pwd
225
226
227def clean_up():
228    list_dirs = os.walk(WORK_DIR)
229    for root, dirs, files in list_dirs:
230        for file in files:
231            if file.startswith('golden'):
232                os.remove(os.path.join(root, file))
233
234    temp_dir = os.path.join(WORK_DIR, 'temp')
235    if os.path.exists(temp_dir):
236        shutil.rmtree(temp_dir)
237
238
239if __name__ == "__main__":
240    if len(sys.argv) > 1 and sys.argv[-1] == '--align':
241        ALIGNED_PARM = ' -a '
242    setup_work_dir()
243    hc_gen = setup_hcgen_compiler()
244    clean_up()
245    print("hc-gen path : " + hc_gen)
246    test_case_list = index_case(WORK_DIR)
247    build_cases(hc_gen, test_case_list)
248