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