12e5b6d6dSopenharmony_ci# © 2021 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci# License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci 42e5b6d6dSopenharmony_ci"""Executes uconfig variations check. 52e5b6d6dSopenharmony_ci 62e5b6d6dSopenharmony_ciSee 72e5b6d6dSopenharmony_cihttp://site.icu-project.org/processes/release/tasks/healthy-code#TOC-Test-uconfig.h-variations 82e5b6d6dSopenharmony_cifor more information. 92e5b6d6dSopenharmony_ci""" 102e5b6d6dSopenharmony_ci 112e5b6d6dSopenharmony_ciimport getopt 122e5b6d6dSopenharmony_ciimport os 132e5b6d6dSopenharmony_ciimport re 142e5b6d6dSopenharmony_ciimport subprocess 152e5b6d6dSopenharmony_ciimport sys 162e5b6d6dSopenharmony_ci 172e5b6d6dSopenharmony_ciexcluded_unit_test_flags = ['UCONFIG_NO_CONVERSION', 'UCONFIG_NO_FILE_IO']; 182e5b6d6dSopenharmony_ci 192e5b6d6dSopenharmony_cidef ReadFile(filename): 202e5b6d6dSopenharmony_ci """Reads a file and returns the content of the file 212e5b6d6dSopenharmony_ci 222e5b6d6dSopenharmony_ci Args: 232e5b6d6dSopenharmony_ci command: string with the filename. 242e5b6d6dSopenharmony_ci 252e5b6d6dSopenharmony_ci Returns: 262e5b6d6dSopenharmony_ci Content of file. 272e5b6d6dSopenharmony_ci """ 282e5b6d6dSopenharmony_ci 292e5b6d6dSopenharmony_ci with open(filename, 'r') as file_handle: 302e5b6d6dSopenharmony_ci return file_handle.read() 312e5b6d6dSopenharmony_ci 322e5b6d6dSopenharmony_cidef RunCmd(command): 332e5b6d6dSopenharmony_ci """Executes the command, returns output and exit code, writes output to log 342e5b6d6dSopenharmony_ci 352e5b6d6dSopenharmony_ci Args: 362e5b6d6dSopenharmony_ci command: string with the command. 372e5b6d6dSopenharmony_ci 382e5b6d6dSopenharmony_ci Returns: 392e5b6d6dSopenharmony_ci stdout and exit code of command execution. 402e5b6d6dSopenharmony_ci """ 412e5b6d6dSopenharmony_ci 422e5b6d6dSopenharmony_ci print(command) 432e5b6d6dSopenharmony_ci p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, 442e5b6d6dSopenharmony_ci stderr=subprocess.STDOUT, close_fds=True) 452e5b6d6dSopenharmony_ci stdout, _ = p.communicate() 462e5b6d6dSopenharmony_ci return stdout, p.returncode 472e5b6d6dSopenharmony_ci 482e5b6d6dSopenharmony_cidef ExtractUConfigNoXXX(uconfig_file): 492e5b6d6dSopenharmony_ci """Parses uconfig.h and returns a list of UCONFIG_NO_XXX labels. 502e5b6d6dSopenharmony_ci Initializes test result structure. 512e5b6d6dSopenharmony_ci 522e5b6d6dSopenharmony_ci Args: 532e5b6d6dSopenharmony_ci uconfig_file: common/unicode/uconfig.h as string. 542e5b6d6dSopenharmony_ci 552e5b6d6dSopenharmony_ci Returns: 562e5b6d6dSopenharmony_ci List of all UCONFIG_NO_XXX flags found in uconfig.h, initialized test 572e5b6d6dSopenharmony_ci result structure. 582e5b6d6dSopenharmony_ci """ 592e5b6d6dSopenharmony_ci 602e5b6d6dSopenharmony_ci uconfig_no_flags_all = [] 612e5b6d6dSopenharmony_ci test_results = {} 622e5b6d6dSopenharmony_ci uconfig_no_regex = r'UCONFIG_NO_[A-Z_]*' 632e5b6d6dSopenharmony_ci 642e5b6d6dSopenharmony_ci # Collect all distinct occurences of UCONFIG_NO_XXX matches in uconfig.h. 652e5b6d6dSopenharmony_ci for uconfig_no_flag in re.finditer(uconfig_no_regex, uconfig_file): 662e5b6d6dSopenharmony_ci if uconfig_no_flag.group(0) not in uconfig_no_flags_all: 672e5b6d6dSopenharmony_ci uconfig_no_flags_all.append(uconfig_no_flag.group(0)) 682e5b6d6dSopenharmony_ci 692e5b6d6dSopenharmony_ci # All UCONFIG_NO_XXX flags found in uconfig.h come in form of a guarded 702e5b6d6dSopenharmony_ci # definition. Verify the existence, report error if not found. 712e5b6d6dSopenharmony_ci for uconfig_no_flag in uconfig_no_flags_all: 722e5b6d6dSopenharmony_ci uconfig_no_def_regex = r'(?m)#ifndef %s\n#\s+define %s\s+0\n#endif$' % ( 732e5b6d6dSopenharmony_ci uconfig_no_flag, uconfig_no_flag) 742e5b6d6dSopenharmony_ci uconfig_no_def_match = re.search(uconfig_no_def_regex, uconfig_file) 752e5b6d6dSopenharmony_ci if not uconfig_no_def_match: 762e5b6d6dSopenharmony_ci print('No definition for flag %s found!\n' % uconfig_no_flag) 772e5b6d6dSopenharmony_ci sys.exit(1) 782e5b6d6dSopenharmony_ci 792e5b6d6dSopenharmony_ci test_results = {f: {'unit_test': False, 'hdr_test': False, 'u_log_tail': '', 'h_log_tail': ''} 802e5b6d6dSopenharmony_ci for f in uconfig_no_flags_all} 812e5b6d6dSopenharmony_ci test_results['all_flags'] = {'unit_test': False, 'hdr_test' : False, 'u_log_tail': '', 822e5b6d6dSopenharmony_ci 'h_log_tail': ''} 832e5b6d6dSopenharmony_ci 842e5b6d6dSopenharmony_ci return uconfig_no_flags_all, test_results 852e5b6d6dSopenharmony_ci 862e5b6d6dSopenharmony_cidef BuildAllFlags(uconfig_no_list): 872e5b6d6dSopenharmony_ci """Builds sequence of -Dflag=1 with each flag from the list.""" 882e5b6d6dSopenharmony_ci 892e5b6d6dSopenharmony_ci flag_list = ['-D' + uconfig_no + '=1' for uconfig_no in uconfig_no_list] 902e5b6d6dSopenharmony_ci 912e5b6d6dSopenharmony_ci return ' '.join(flag_list) 922e5b6d6dSopenharmony_ci 932e5b6d6dSopenharmony_cidef RunUnitTests(uconfig_no_list, test_results): 942e5b6d6dSopenharmony_ci """Iterates over all flags, sets each individually during ICU configuration 952e5b6d6dSopenharmony_ci and executes the ICU4C unit tests. 962e5b6d6dSopenharmony_ci 972e5b6d6dSopenharmony_ci Args: 982e5b6d6dSopenharmony_ci uconfig_no_list: list of all UCONFIG_NO_XXX flags to test with. 992e5b6d6dSopenharmony_ci test_results: dictionary to record test run results. 1002e5b6d6dSopenharmony_ci 1012e5b6d6dSopenharmony_ci Returns: 1022e5b6d6dSopenharmony_ci test_results: updated test result entries. 1032e5b6d6dSopenharmony_ci """ 1042e5b6d6dSopenharmony_ci 1052e5b6d6dSopenharmony_ci for uconfig_no in uconfig_no_list: 1062e5b6d6dSopenharmony_ci conf_log, exit_code = RunCmd( 1072e5b6d6dSopenharmony_ci './runConfigureICU Linux CPPFLAGS=\"-D%s=1"' % uconfig_no) 1082e5b6d6dSopenharmony_ci if exit_code != 0: 1092e5b6d6dSopenharmony_ci print('ICU4C configuration for flag %s failed' % uconfig_no) 1102e5b6d6dSopenharmony_ci print('Last 25 lines:\n%s\n' % '\n'.join(conf_log.decode('utf-8').splitlines()[-25:])) 1112e5b6d6dSopenharmony_ci sys.exit(1) 1122e5b6d6dSopenharmony_ci print('Running unit tests with %s set to 1.' % uconfig_no) 1132e5b6d6dSopenharmony_ci run_log, exit_code = RunCmd('make -j2 check') 1142e5b6d6dSopenharmony_ci test_results[uconfig_no]['unit_test'] = (exit_code == 0) 1152e5b6d6dSopenharmony_ci test_results[uconfig_no]['u_log_tail'] = \ 1162e5b6d6dSopenharmony_ci '\n'.join(run_log.decode('utf-8').splitlines()[-50:]) 1172e5b6d6dSopenharmony_ci RunCmd('make clean') 1182e5b6d6dSopenharmony_ci 1192e5b6d6dSopenharmony_ci # Configure ICU with all UCONFIG_NO_XXX flags set to 1 and execute 1202e5b6d6dSopenharmony_ci # the ICU4C unit tests. 1212e5b6d6dSopenharmony_ci all_unit_test_config_no = BuildAllFlags(uconfig_no_list) 1222e5b6d6dSopenharmony_ci conf_log, exit_code = RunCmd( 1232e5b6d6dSopenharmony_ci 'CPPFLAGS=\"%s\" ./runConfigureICU Linux' % all_unit_test_config_no) 1242e5b6d6dSopenharmony_ci if exit_code != 0: 1252e5b6d6dSopenharmony_ci print('ICU configuration with all flags set failed') 1262e5b6d6dSopenharmony_ci print('Last 25 lines:\n%s\n' % '\n'.join(conf_log.decode('utf-8').splitlines()[-25:])) 1272e5b6d6dSopenharmony_ci sys.exit(1) 1282e5b6d6dSopenharmony_ci print('Running unit tests with all flags set to 1.') 1292e5b6d6dSopenharmony_ci run_log, exit_code = RunCmd('make -j2 check') 1302e5b6d6dSopenharmony_ci test_results['all_flags']['unit_test'] = (exit_code == 0) 1312e5b6d6dSopenharmony_ci test_results['all_flags']['u_log_tail'] = \ 1322e5b6d6dSopenharmony_ci '\n'.join(run_log.decode('utf-8').splitlines()[-50:]) 1332e5b6d6dSopenharmony_ci RunCmd('make clean') 1342e5b6d6dSopenharmony_ci 1352e5b6d6dSopenharmony_ci return test_results 1362e5b6d6dSopenharmony_ci 1372e5b6d6dSopenharmony_cidef RunHeaderTests(uconfig_no_list, test_results): 1382e5b6d6dSopenharmony_ci """Iterates over all flags and executes the header test. 1392e5b6d6dSopenharmony_ci 1402e5b6d6dSopenharmony_ci Args: 1412e5b6d6dSopenharmony_ci uconfig_no_list: list of all UCONFIG_NO_XXX flags to test with. 1422e5b6d6dSopenharmony_ci test_results: dictionary to record test run results. 1432e5b6d6dSopenharmony_ci 1442e5b6d6dSopenharmony_ci Returns: 1452e5b6d6dSopenharmony_ci test_results: updated test result entries. 1462e5b6d6dSopenharmony_ci """ 1472e5b6d6dSopenharmony_ci 1482e5b6d6dSopenharmony_ci # Header tests needs different setup. 1492e5b6d6dSopenharmony_ci RunCmd('mkdir /tmp/icu_cnfg') 1502e5b6d6dSopenharmony_ci conf_log, exit_code = RunCmd('./runConfigureICU Linux --prefix=/tmp/icu_cnfg') 1512e5b6d6dSopenharmony_ci if exit_code != 0: 1522e5b6d6dSopenharmony_ci print('ICU4C configuration for header test failed!') 1532e5b6d6dSopenharmony_ci print('Last 25 lines:\n%s\n' % '\n'.join(conf_log.decode('utf-8').splitlines()[-25:])) 1542e5b6d6dSopenharmony_ci sys.exit(1) 1552e5b6d6dSopenharmony_ci 1562e5b6d6dSopenharmony_ci inst_log, exit_code = RunCmd('make -j2 install') 1572e5b6d6dSopenharmony_ci if exit_code != 0: 1582e5b6d6dSopenharmony_ci print('make install failed!') 1592e5b6d6dSopenharmony_ci print('Last 25 lines:\n%s\n' % '\n'.join(inst_log.decode('utf-8').splitlines()[-25:])) 1602e5b6d6dSopenharmony_ci sys.exit(1) 1612e5b6d6dSopenharmony_ci 1622e5b6d6dSopenharmony_ci for uconfig_no in uconfig_no_list: 1632e5b6d6dSopenharmony_ci print('Running header tests with %s set to 1.' % uconfig_no) 1642e5b6d6dSopenharmony_ci run_log, exit_code = RunCmd( 1652e5b6d6dSopenharmony_ci 'PATH=/tmp/icu_cnfg/bin:$PATH make -C test/hdrtst UCONFIG_NO=\"-D%s=1\" check' % uconfig_no) 1662e5b6d6dSopenharmony_ci test_results[uconfig_no]['hdr_test'] = (exit_code == 0) 1672e5b6d6dSopenharmony_ci test_results[uconfig_no]['h_log_tail'] = \ 1682e5b6d6dSopenharmony_ci '\n'.join(run_log.decode('utf-8').splitlines()[-50:]) 1692e5b6d6dSopenharmony_ci 1702e5b6d6dSopenharmony_ci all_hdr_test_flags = BuildAllFlags(uconfig_no_list) 1712e5b6d6dSopenharmony_ci print('Running header tests with all flags set to 1.') 1722e5b6d6dSopenharmony_ci run_log, exit_code = RunCmd( 1732e5b6d6dSopenharmony_ci 'PATH=/tmp/icu_cnfg/bin:$PATH make -C test/hdrtst UCONFIG_NO=\"%s\" check' % all_hdr_test_flags) 1742e5b6d6dSopenharmony_ci test_results['all_flags']['hdr_test'] = (exit_code == 0) 1752e5b6d6dSopenharmony_ci test_results['all_flags']['h_log_tail'] = \ 1762e5b6d6dSopenharmony_ci '\n'.join(run_log.decode('utf-8').splitlines()[-50:]) 1772e5b6d6dSopenharmony_ci 1782e5b6d6dSopenharmony_ci return test_results 1792e5b6d6dSopenharmony_ci 1802e5b6d6dSopenharmony_cidef main(): 1812e5b6d6dSopenharmony_ci # Read the options and determine what to run. 1822e5b6d6dSopenharmony_ci run_hdr = False 1832e5b6d6dSopenharmony_ci run_unit = False 1842e5b6d6dSopenharmony_ci optlist, _ = getopt.getopt(sys.argv[1:], "pu") 1852e5b6d6dSopenharmony_ci for o, _ in optlist: 1862e5b6d6dSopenharmony_ci if o == "-p": 1872e5b6d6dSopenharmony_ci run_hdr = True 1882e5b6d6dSopenharmony_ci elif o == "-u": 1892e5b6d6dSopenharmony_ci run_unit = True 1902e5b6d6dSopenharmony_ci 1912e5b6d6dSopenharmony_ci os.chdir('icu4c/source') 1922e5b6d6dSopenharmony_ci orig_uconfig_file = ReadFile('common/unicode/uconfig.h') 1932e5b6d6dSopenharmony_ci 1942e5b6d6dSopenharmony_ci all_uconfig_no_flags, test_results = ExtractUConfigNoXXX(orig_uconfig_file) 1952e5b6d6dSopenharmony_ci if not all_uconfig_no_flags: 1962e5b6d6dSopenharmony_ci print('No UCONFIG_NO_XXX flags found!\n') 1972e5b6d6dSopenharmony_ci sys.exit(1) 1982e5b6d6dSopenharmony_ci 1992e5b6d6dSopenharmony_ci if run_unit: 2002e5b6d6dSopenharmony_ci RunUnitTests( 2012e5b6d6dSopenharmony_ci [u for u in all_uconfig_no_flags if u not in excluded_unit_test_flags], 2022e5b6d6dSopenharmony_ci test_results) 2032e5b6d6dSopenharmony_ci if run_hdr: 2042e5b6d6dSopenharmony_ci RunHeaderTests(all_uconfig_no_flags, test_results) 2052e5b6d6dSopenharmony_ci 2062e5b6d6dSopenharmony_ci # Review test results and report any failures. 2072e5b6d6dSopenharmony_ci # 'outcome' will be returned by sys.exit(); 0 indicates success, any 2082e5b6d6dSopenharmony_ci # other value indicates failure. 2092e5b6d6dSopenharmony_ci outcome = 0 2102e5b6d6dSopenharmony_ci print('Summary:\n') 2112e5b6d6dSopenharmony_ci for uconfig_no in all_uconfig_no_flags: 2122e5b6d6dSopenharmony_ci if run_unit and (uconfig_no not in excluded_unit_test_flags): 2132e5b6d6dSopenharmony_ci if not test_results[uconfig_no]['unit_test']: 2142e5b6d6dSopenharmony_ci outcome = 1 2152e5b6d6dSopenharmony_ci print('\n============================================================\n') 2162e5b6d6dSopenharmony_ci print('%s: unit tests fail' % uconfig_no) 2172e5b6d6dSopenharmony_ci print('Last 50 lines from log file:\n%s\n' % test_results[uconfig_no]['u_log_tail']) 2182e5b6d6dSopenharmony_ci print('\n============================================================\n') 2192e5b6d6dSopenharmony_ci if run_hdr and not test_results[uconfig_no]['hdr_test']: 2202e5b6d6dSopenharmony_ci outcome = 1 2212e5b6d6dSopenharmony_ci print('\n============================================================\n') 2222e5b6d6dSopenharmony_ci print('%s: header tests fails' % uconfig_no) 2232e5b6d6dSopenharmony_ci print('Last 50 lines from log file:\n%s\n' % test_results[uconfig_no]['h_log_tail']) 2242e5b6d6dSopenharmony_ci print('\n============================================================\n') 2252e5b6d6dSopenharmony_ci 2262e5b6d6dSopenharmony_ci if run_unit and not test_results['all_flags']['unit_test']: 2272e5b6d6dSopenharmony_ci outcome = 1 2282e5b6d6dSopenharmony_ci print('\n============================================================\n') 2292e5b6d6dSopenharmony_ci print('all flags to 1: unit tests fail!') 2302e5b6d6dSopenharmony_ci print('Last 50 lines from log file:\n%s\n' % test_results['all_flags']['u_log_tail']) 2312e5b6d6dSopenharmony_ci print('\n============================================================\n') 2322e5b6d6dSopenharmony_ci if run_hdr and not test_results['all_flags']['hdr_test']: 2332e5b6d6dSopenharmony_ci outcome = 1 2342e5b6d6dSopenharmony_ci print('\n============================================================\n') 2352e5b6d6dSopenharmony_ci print('all flags to 1: header tests fail!') 2362e5b6d6dSopenharmony_ci print('Last 50 lines from log file: %s\n ' % test_results['all_flags']['h_log_tail']) 2372e5b6d6dSopenharmony_ci print('\n============================================================\n') 2382e5b6d6dSopenharmony_ci if outcome == 0: 2392e5b6d6dSopenharmony_ci print('Tests pass for all uconfig variations!') 2402e5b6d6dSopenharmony_ci sys.exit(outcome) 2412e5b6d6dSopenharmony_ci 2422e5b6d6dSopenharmony_ci 2432e5b6d6dSopenharmony_ciif __name__ == '__main__': 2442e5b6d6dSopenharmony_ci main() 245