• 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 stat
36import subprocess
37import sys
38import base64
39
40
41class TestConfig(object):
42    CMAKE_GEN_PATH = "cmake-build-debug/"
43    WORK_DIR = ""
44    ERROR_COLOR_PREFIX = "\033[31m"
45    ERROR_COLOR_END = "\033[0m"
46    ALIGNED_PARM = ''
47
48
49def setup_hcgen_compiler():
50    if len(sys.argv) > 1:
51        hcgen_path = os.path.abspath(sys.argv[1])
52        if hcgen_path.find('hc-gen') >= 0 and os.access(hcgen_path, os.X_OK):
53            print('use specified hsc:' + hcgen_path)
54            return hcgen_path
55
56    source_root = '../../'
57    compiler_name = "hc-gen"
58    if platform.system() == "Windows":
59        source_root = source_root.replace("/", "\\")
60        compiler_name += ".exe"
61
62    source_root = os.path.abspath(os.path.join(TestConfig.WORK_DIR, source_root))
63    hcgen_path = os.path.join(source_root, compiler_name)
64    if not os.access(hcgen_path, os.X_OK):
65        hcgen_path = os.path.join(source_root, TestConfig.CMAKE_GEN_PATH, compiler_name)
66        if not os.access(hcgen_path, os.X_OK):
67            print("Error: hcgen not found, please make first")
68            exit(1)
69
70    return hcgen_path
71
72
73def index_case(case_path):
74    cases = []
75    for directory in os.listdir(case_path):
76        if os.path.isdir(os.path.join(case_path, directory)):
77            cases.append(directory)
78    cases.sort()
79    return cases
80
81
82def save_compile_result(mode, case_name, status, output):
83    result_file_name = os.path.join(TestConfig.WORK_DIR, case_name,
84                                    'golden_%s_compile_result.txt' % mode)
85    flags = os.O_RDWR | os.O_CREAT
86    modes = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH
87    with os.fdopen(os.open(result_file_name, flags, modes),
88                   "w", encoding="utf-8") as result_output:
89        status_str = "[compile exit status]:" + str(status)
90        output_str = "\n[compile console output]:\n" + output
91        result_output.write(status_str)
92        result_output.write(output_str)
93
94
95def gen_decompile_golden(hcgen_path, case_name):
96    source_file = os.path.join(TestConfig.WORK_DIR, case_name, 'golden.hcb')
97    target_file = os.path.join(TestConfig.WORK_DIR, case_name, 'golden')
98    command = "%s -o %s -d %s" % (hcgen_path, target_file, source_file)
99    status, output = subprocess.getstatusoutput(command)
100    if status:
101        print('case %s decompile fail:\n %s, status=%d' %
102              (case_name, output, status))
103
104    return status == 0
105
106
107def recode_hcb_file(file_path):
108    with open(file_path, 'rb') as hcb_file:
109        content = hcb_file.read()
110        hcb_file.close()
111
112    with open(file_path, 'wb') as hcb_file:
113        base64_content = base64.b64encode(content)
114        hcb_file.write(base64_content)
115        hcb_file.close()
116
117
118def build_binary(hcgen_path, case_name):
119    source_file = os.path.join(TestConfig.WORK_DIR, case_name, 'case.hcs')
120    target_file = os.path.join(TestConfig.WORK_DIR, case_name, 'golden')
121    command = "%s %s -o %s %s" % \
122              (hcgen_path, TestConfig.ALIGNED_PARM, target_file, source_file)
123    status, output = subprocess.getstatusoutput(command)
124    if case_name.endswith('_ei'):
125        if status == 0:
126            print("CASE_ERROR:error identify case " + case_name
127                  + "expect build fail but success at binary mode")
128            return False
129    elif status != 0:
130        print("CASE_ERROR:case " + case_name
131              + " expect build success but failed at binary mode")
132        return False
133    output = output.replace(TestConfig.WORK_DIR, ".").replace('\\', '/') \
134        .replace(TestConfig.ERROR_COLOR_PREFIX, "") \
135        .replace(TestConfig.ERROR_COLOR_END, "").strip()
136
137    save_compile_result('binary', case_name, status, output)
138
139    result = True
140    if status == 0:
141        result = gen_decompile_golden(hcgen_path, case_name)
142        if result:
143            recode_hcb_file(target_file + '.hcb')
144    return result
145
146
147def build_text(hcgen_path, case_name):
148    source_file = os.path.join(TestConfig.WORK_DIR, case_name, 'case.hcs')
149    target_file = os.path.join(TestConfig.WORK_DIR, case_name, 'golden')
150    command = "%s -t -o %s %s" % (hcgen_path, target_file, source_file)
151    status, output = subprocess.getstatusoutput(command)
152    if case_name.endswith('_ei') or case_name.find('node_duplicate_name') >= 0:
153        if status == 0:
154            print("CASE_ERROR:error identify case "
155                  + case_name + " expect build fail but success at text mode")
156            print(output)
157            return False
158    elif status != 0:
159        print("CASE_ERROR:case " + case_name
160              + " expect build success but failed at text mode")
161        print(output)
162        return False
163    output = output.replace(TestConfig.WORK_DIR, ".").replace('\\', '/') \
164        .replace(TestConfig.ERROR_COLOR_PREFIX, "") \
165        .replace(TestConfig.ERROR_COLOR_END, "").strip()
166
167    save_compile_result('text', case_name, status, output)
168
169    if status == 0:
170        os.rename(target_file + '.c', target_file + '.c.gen')
171        os.rename(target_file + '.h', target_file + '.h.gen')
172    return True
173
174
175def build_macro(hcgen_path, case_name):
176    source_file = os.path.join(TestConfig.WORK_DIR, case_name, 'case.hcs')
177    target_file = os.path.join(TestConfig.WORK_DIR, case_name, 'macro')
178    command = "%s -m -o %s %s" % (hcgen_path, target_file, source_file)
179    status, output = subprocess.getstatusoutput(command)
180    if case_name.endswith('_ei'):
181        if status == 0:
182            print("CASE_ERROR:error identify case "
183                  + case_name + " expect build fail but success at macro mode")
184            print(output)
185            return False
186    elif status != 0:
187        print("CASE_ERROR:case " + case_name
188              + " expect build success but failed at macro mode")
189        print(output)
190        return False
191    output = output.replace(TestConfig.WORK_DIR, ".").replace('\\', '/') \
192        .replace(TestConfig.ERROR_COLOR_PREFIX, "") \
193        .replace(TestConfig.ERROR_COLOR_END, "").strip()
194
195    save_compile_result('macro', case_name, status, output)
196
197    if status == 0:
198        os.rename(target_file + '.h', target_file + '.h.gen')
199    return True
200
201
202def build_cases(hcgen_path, cases):
203    index = 1
204    failed_cases = []
205    for case in cases:
206        print('[%02d/%d] build %s' % (index, len(cases), case))
207        text_compile = build_text(hcgen_path, case)
208        binary_compile = build_binary(hcgen_path, case)
209        macro_compile = build_macro(hcgen_path, case)
210        if not text_compile or not binary_compile or not macro_compile:
211            failed_cases.append(case)
212        index += 1
213
214    print("\nUpdate cases result :\ntotal case: %d, failed: %d, success: %d" %
215          (len(cases), len(failed_cases), len(cases) - len(failed_cases)))
216    if len(failed_cases) > 0:
217        print("Failed case as below:")
218        for case in failed_cases:
219            print(case)
220
221
222def setup_work_dir():
223    pwd = os.path.abspath(sys.argv[0])
224    pwd = pwd[:pwd.rfind(os.sep)]
225    TestConfig.WORK_DIR = pwd
226
227
228def clean_up():
229    list_dirs = os.walk(TestConfig.WORK_DIR)
230    for root, dirs, files in list_dirs:
231        for file in files:
232            if file.startswith('golden'):
233                os.remove(os.path.join(root, file))
234
235    temp_dir = os.path.join(TestConfig.WORK_DIR, 'temp')
236    if os.path.exists(temp_dir):
237        shutil.rmtree(temp_dir)
238
239
240if __name__ == "__main__":
241    if len(sys.argv) > 1 and sys.argv[-1] == '--align':
242        TestConfig.ALIGNED_PARM = ' -a '
243    setup_work_dir()
244    hc_gen = setup_hcgen_compiler()
245    clean_up()
246    print("hc-gen path : " + hc_gen)
247    test_case_list = index_case(TestConfig.WORK_DIR)
248    build_cases(hc_gen, test_case_list)
249