xref: /arkcompiler/ets_frontend/test262/utils.py (revision 3af6ab5f)
13af6ab5fSopenharmony_ci#!/usr/bin/env python3
23af6ab5fSopenharmony_ci# -*- coding: utf-8 -*-
33af6ab5fSopenharmony_ci
43af6ab5fSopenharmony_ci"""
53af6ab5fSopenharmony_ciCopyright (c) 2021-2024 Huawei Device Co., Ltd.
63af6ab5fSopenharmony_ciLicensed under the Apache License, Version 2.0 (the "License");
73af6ab5fSopenharmony_ciyou may not use this file except in compliance with the License.
83af6ab5fSopenharmony_ciYou may obtain a copy of the License at
93af6ab5fSopenharmony_ci
103af6ab5fSopenharmony_ci    http://www.apache.org/licenses/LICENSE-2.0
113af6ab5fSopenharmony_ci
123af6ab5fSopenharmony_ciUnless required by applicable law or agreed to in writing, software
133af6ab5fSopenharmony_cidistributed under the License is distributed on an "AS IS" BASIS,
143af6ab5fSopenharmony_ciWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
153af6ab5fSopenharmony_ciSee the License for the specific language governing permissions and
163af6ab5fSopenharmony_cilimitations under the License.
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ciDescription: Implement the public interface in the 262 use case
193af6ab5fSopenharmony_ci"""
203af6ab5fSopenharmony_ci
213af6ab5fSopenharmony_ciimport os
223af6ab5fSopenharmony_ciimport signal
233af6ab5fSopenharmony_ciimport sys
243af6ab5fSopenharmony_ciimport subprocess
253af6ab5fSopenharmony_ciimport datetime
263af6ab5fSopenharmony_ciimport time
273af6ab5fSopenharmony_ciimport shutil
283af6ab5fSopenharmony_ciimport platform
293af6ab5fSopenharmony_ciimport re
303af6ab5fSopenharmony_cifrom config import DEFAULT_TIMEOUT, DEFAULT_RETRIES
313af6ab5fSopenharmony_ci
323af6ab5fSopenharmony_ciTERM_NORMAL = '\033[0m'
333af6ab5fSopenharmony_ciTERM_YELLOW = '\033[1;33m'
343af6ab5fSopenharmony_ciTERM_BLUE = '\033[1;34m'
353af6ab5fSopenharmony_ciTERM_RED = '\033[1;31m'
363af6ab5fSopenharmony_ciTERM_FUCHSIA = '\033[1;35m'
373af6ab5fSopenharmony_ci
383af6ab5fSopenharmony_ciABC_EXT = ".abc"
393af6ab5fSopenharmony_ciTEMP_ABC_EXT = ".temp.abc"
403af6ab5fSopenharmony_ciTXT_EXT = ".txt"
413af6ab5fSopenharmony_ciTEMP_TXT_EXT = ".temp.txt"
423af6ab5fSopenharmony_ci
433af6ab5fSopenharmony_ci
443af6ab5fSopenharmony_cidef output(retcode, msg):
453af6ab5fSopenharmony_ci    if retcode == 0:
463af6ab5fSopenharmony_ci        if msg != '':
473af6ab5fSopenharmony_ci            print(str(msg))
483af6ab5fSopenharmony_ci    elif retcode == -6:
493af6ab5fSopenharmony_ci        sys.stderr.write("Aborted (core dumped)")
503af6ab5fSopenharmony_ci    elif retcode == -4:
513af6ab5fSopenharmony_ci        sys.stderr.write("Aborted (core dumped)")
523af6ab5fSopenharmony_ci    elif retcode == -11:
533af6ab5fSopenharmony_ci        sys.stderr.write("Segmentation fault (core dumped)")
543af6ab5fSopenharmony_ci    elif msg != '':
553af6ab5fSopenharmony_ci        sys.stderr.write(str(msg))
563af6ab5fSopenharmony_ci    else:
573af6ab5fSopenharmony_ci        sys.stderr.write("Unknown Error: " + str(retcode))
583af6ab5fSopenharmony_ci
593af6ab5fSopenharmony_ci
603af6ab5fSopenharmony_cidef filter_arm_specific_errors(errs_str):
613af6ab5fSopenharmony_ci    list_errs = []
623af6ab5fSopenharmony_ci    for err in errs_str.split("\n"):
633af6ab5fSopenharmony_ci        if err:
643af6ab5fSopenharmony_ci            if ("memset will be used instead" not in err and
653af6ab5fSopenharmony_ci                "This is the expected behaviour if you are running under QEMU" not in err and
663af6ab5fSopenharmony_ci                "Can't connect to server" not in err):
673af6ab5fSopenharmony_ci                list_errs.append(err)
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_ci    if len(list_errs) != 0:
703af6ab5fSopenharmony_ci        output(1, " ".join(list_errs))
713af6ab5fSopenharmony_ci        return False
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_ci    return True
743af6ab5fSopenharmony_ci
753af6ab5fSopenharmony_ci
763af6ab5fSopenharmony_cidef exec_command(cmd_args, timeout=DEFAULT_TIMEOUT, custom_cwd=None):
773af6ab5fSopenharmony_ci    proc = subprocess.Popen(cmd_args,
783af6ab5fSopenharmony_ci                            stderr=subprocess.PIPE,
793af6ab5fSopenharmony_ci                            stdout=subprocess.PIPE,
803af6ab5fSopenharmony_ci                            close_fds=True,
813af6ab5fSopenharmony_ci                            start_new_session=True,
823af6ab5fSopenharmony_ci                            cwd=custom_cwd)
833af6ab5fSopenharmony_ci    cmd_string = " ".join(cmd_args)
843af6ab5fSopenharmony_ci    code_format = 'utf-8'
853af6ab5fSopenharmony_ci    if platform.system() == "Windows":
863af6ab5fSopenharmony_ci        code_format = 'gbk'
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_ci    try:
893af6ab5fSopenharmony_ci        (output_res, errs) = proc.communicate(timeout=timeout)
903af6ab5fSopenharmony_ci        ret_code = proc.poll()
913af6ab5fSopenharmony_ci
923af6ab5fSopenharmony_ci        errs_str = errs.decode(code_format, 'ignore')
933af6ab5fSopenharmony_ci        if filter_arm_specific_errors(errs_str):
943af6ab5fSopenharmony_ci            errs = None
953af6ab5fSopenharmony_ci        else:
963af6ab5fSopenharmony_ci            return 1
973af6ab5fSopenharmony_ci
983af6ab5fSopenharmony_ci        if ret_code and ret_code != 1:
993af6ab5fSopenharmony_ci            code = ret_code
1003af6ab5fSopenharmony_ci            msg = f"Command {cmd_string}: \n"
1013af6ab5fSopenharmony_ci            msg += f"error: {errs_str}"
1023af6ab5fSopenharmony_ci        else:
1033af6ab5fSopenharmony_ci            code = 0
1043af6ab5fSopenharmony_ci            msg = str(output_res.decode(code_format, 'ignore'))
1053af6ab5fSopenharmony_ci
1063af6ab5fSopenharmony_ci    except subprocess.TimeoutExpired:
1073af6ab5fSopenharmony_ci        proc.kill()
1083af6ab5fSopenharmony_ci        proc.terminate()
1093af6ab5fSopenharmony_ci        os.kill(proc.pid, signal.SIGTERM)
1103af6ab5fSopenharmony_ci        code = 1
1113af6ab5fSopenharmony_ci        msg = f"Timeout:'{cmd_string}' timed out after' {str(timeout)} seconds"
1123af6ab5fSopenharmony_ci    except Exception as err:
1133af6ab5fSopenharmony_ci        code = 1
1143af6ab5fSopenharmony_ci        msg = f"{cmd_string}: unknown error: {str(err)}"
1153af6ab5fSopenharmony_ci    output(code, msg)
1163af6ab5fSopenharmony_ci    return code
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_ci
1193af6ab5fSopenharmony_cidef print_command(cmd_args):
1203af6ab5fSopenharmony_ci    sys.stderr.write("\n")
1213af6ab5fSopenharmony_ci    sys.stderr.write(" ".join(cmd_args))
1223af6ab5fSopenharmony_ci    sys.stderr.write("\n")
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci
1253af6ab5fSopenharmony_ci# for debug use, to keep aot file
1263af6ab5fSopenharmony_cidef run_command(cmd_args):
1273af6ab5fSopenharmony_ci    return subprocess.run(" ".join(cmd_args))
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_ci
1303af6ab5fSopenharmony_cidef get_formated_path(path):
1313af6ab5fSopenharmony_ci    # In the case of Windows, it is necessary to convert ' \\' to '/', otherwise there will be a crash or the file cannot be found
1323af6ab5fSopenharmony_ci    # Maintain consistent interface path with DevEco Studio
1333af6ab5fSopenharmony_ci    if platform.system() == "Windows":
1343af6ab5fSopenharmony_ci        return path.replace("\\", "/")
1353af6ab5fSopenharmony_ci    return path
1363af6ab5fSopenharmony_ci
1373af6ab5fSopenharmony_ci
1383af6ab5fSopenharmony_cidef current_time():
1393af6ab5fSopenharmony_ci    return datetime.datetime.now().strftime('%m-%d %H:%M:%S.%f')
1403af6ab5fSopenharmony_ci
1413af6ab5fSopenharmony_ci
1423af6ab5fSopenharmony_ciclass Logging():
1433af6ab5fSopenharmony_ci    def __init__(self):
1443af6ab5fSopenharmony_ci        self.is_logging = True
1453af6ab5fSopenharmony_ci
1463af6ab5fSopenharmony_ci    def debug(self, info):
1473af6ab5fSopenharmony_ci        if self.is_logging:
1483af6ab5fSopenharmony_ci            print(
1493af6ab5fSopenharmony_ci                f'{current_time()} D:>>>  {TERM_BLUE}{str(info)}{TERM_NORMAL}')
1503af6ab5fSopenharmony_ci
1513af6ab5fSopenharmony_ci    def info(self, info):
1523af6ab5fSopenharmony_ci        if self.is_logging:
1533af6ab5fSopenharmony_ci            if len(str(info)) > 100:
1543af6ab5fSopenharmony_ci                print(f'{current_time()} I:>>> \n{str(info)} ')
1553af6ab5fSopenharmony_ci            else:
1563af6ab5fSopenharmony_ci                print(f'{current_time()} I:>>>    {str(info)} ')
1573af6ab5fSopenharmony_ci
1583af6ab5fSopenharmony_ci
1593af6ab5fSopenharmony_ciLOGGING = Logging()
1603af6ab5fSopenharmony_ci
1613af6ab5fSopenharmony_ci
1623af6ab5fSopenharmony_ciclass Command():
1633af6ab5fSopenharmony_ci    def __init__(self, cmd):
1643af6ab5fSopenharmony_ci        self.cmd = cmd
1653af6ab5fSopenharmony_ci
1663af6ab5fSopenharmony_ci    def run(self):
1673af6ab5fSopenharmony_ci        LOGGING.debug("command: " + self.cmd)
1683af6ab5fSopenharmony_ci        out = os.popen(self.cmd).read()
1693af6ab5fSopenharmony_ci        LOGGING.info(out)
1703af6ab5fSopenharmony_ci        return out
1713af6ab5fSopenharmony_ci
1723af6ab5fSopenharmony_ci
1733af6ab5fSopenharmony_cidef run_cmd(command):
1743af6ab5fSopenharmony_ci    cmd = Command(command)
1753af6ab5fSopenharmony_ci    return cmd.run()
1763af6ab5fSopenharmony_ci
1773af6ab5fSopenharmony_ci
1783af6ab5fSopenharmony_ciclass CommandCwd():
1793af6ab5fSopenharmony_ci    def __init__(self, cmds, cwd):
1803af6ab5fSopenharmony_ci        self.cmds = cmds
1813af6ab5fSopenharmony_ci        self.cwd = cwd
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_ci    def run(self):
1843af6ab5fSopenharmony_ci        cmd = " ".join(self.cmds)
1853af6ab5fSopenharmony_ci        LOGGING.debug("command: " + cmd + " | " + "dir: " + self.cwd)
1863af6ab5fSopenharmony_ci        if platform.system() == "Windows" :
1873af6ab5fSopenharmony_ci            proc = subprocess.Popen(self.cmds, cwd=self.cwd ,shell=True)
1883af6ab5fSopenharmony_ci        else :
1893af6ab5fSopenharmony_ci            proc = subprocess.Popen(self.cmds, cwd=self.cwd)
1903af6ab5fSopenharmony_ci        return proc.wait()
1913af6ab5fSopenharmony_ci
1923af6ab5fSopenharmony_ci
1933af6ab5fSopenharmony_cidef run_cmd_cwd(commands, cwd=os.getcwd()):
1943af6ab5fSopenharmony_ci    cmd = CommandCwd(commands, cwd)
1953af6ab5fSopenharmony_ci    return cmd.run()
1963af6ab5fSopenharmony_ci
1973af6ab5fSopenharmony_ci
1983af6ab5fSopenharmony_cidef sleep(duration):
1993af6ab5fSopenharmony_ci    LOGGING.debug("sleeping %d" % duration)
2003af6ab5fSopenharmony_ci    time.sleep(duration)
2013af6ab5fSopenharmony_ci
2023af6ab5fSopenharmony_ci
2033af6ab5fSopenharmony_cidef write_file(save_file, result):
2043af6ab5fSopenharmony_ci    LOGGING.debug(f"write file:{save_file}")
2053af6ab5fSopenharmony_ci    with open(save_file, "a+") as file:
2063af6ab5fSopenharmony_ci        file.write(result + "\n")
2073af6ab5fSopenharmony_ci        file.flush()
2083af6ab5fSopenharmony_ci
2093af6ab5fSopenharmony_ci
2103af6ab5fSopenharmony_cidef remove_dir(path):
2113af6ab5fSopenharmony_ci    if os.path.exists(path):
2123af6ab5fSopenharmony_ci        shutil.rmtree(path)
2133af6ab5fSopenharmony_ci
2143af6ab5fSopenharmony_ci
2153af6ab5fSopenharmony_cidef remove_file(file):
2163af6ab5fSopenharmony_ci    if os.path.exists(file):
2173af6ab5fSopenharmony_ci        os.remove(file)
2183af6ab5fSopenharmony_ci
2193af6ab5fSopenharmony_ci
2203af6ab5fSopenharmony_cidef mkdir(path):
2213af6ab5fSopenharmony_ci    if not os.path.exists(path):
2223af6ab5fSopenharmony_ci        os.makedirs(path)
2233af6ab5fSopenharmony_ci
2243af6ab5fSopenharmony_ci
2253af6ab5fSopenharmony_cidef report_command(cmd_type, cmd, env=None):
2263af6ab5fSopenharmony_ci    sys.stderr.write(f'{TERM_BLUE}{cmd_type}{TERM_NORMAL}\n')
2273af6ab5fSopenharmony_ci    if env is not None:
2283af6ab5fSopenharmony_ci        sys.stderr.write(''.join(f'{TERM_BLUE}{var}={val} \\{TERM_NORMAL}\n'
2293af6ab5fSopenharmony_ci                                 for var, val in sorted(env.items())))
2303af6ab5fSopenharmony_ci    cmd_str = (f'{TERM_NORMAL}\n\t{TERM_BLUE}').join(cmd)
2313af6ab5fSopenharmony_ci    sys.stderr.write(f'\t{TERM_BLUE}{cmd_str}{TERM_NORMAL}\n')
2323af6ab5fSopenharmony_ci    sys.stderr.write("\n")
2333af6ab5fSopenharmony_ci
2343af6ab5fSopenharmony_ci
2353af6ab5fSopenharmony_cidef git_clone(git_url, code_dir):
2363af6ab5fSopenharmony_ci    cmd = ['git', 'clone', git_url, code_dir]
2373af6ab5fSopenharmony_ci    retries = 1
2383af6ab5fSopenharmony_ci    while retries <= DEFAULT_RETRIES:
2393af6ab5fSopenharmony_ci        ret = run_cmd_cwd(cmd)
2403af6ab5fSopenharmony_ci        if ret == 0:
2413af6ab5fSopenharmony_ci            break
2423af6ab5fSopenharmony_ci        else:
2433af6ab5fSopenharmony_ci            print(f"\n warning: Atempt: #{retries} to clone '{git_url}' failed. Try cloining again")
2443af6ab5fSopenharmony_ci            retries += 1
2453af6ab5fSopenharmony_ci    assert not ret, f"\n error: Cloning '{git_url}' failed."
2463af6ab5fSopenharmony_ci
2473af6ab5fSopenharmony_ci
2483af6ab5fSopenharmony_cidef git_checkout(git_bash, cwd):
2493af6ab5fSopenharmony_ci    cmd = ['git', 'checkout', '-f', git_bash]
2503af6ab5fSopenharmony_ci    ret = run_cmd_cwd(cmd, cwd)
2513af6ab5fSopenharmony_ci    assert not ret, f"\n error: git checkout '{git_bash}' failed."
2523af6ab5fSopenharmony_ci
2533af6ab5fSopenharmony_ci
2543af6ab5fSopenharmony_cidef git_apply(patch_file, cwd):
2553af6ab5fSopenharmony_ci    cmd = ['git', 'apply', patch_file]
2563af6ab5fSopenharmony_ci    ret = run_cmd_cwd(cmd, cwd)
2573af6ab5fSopenharmony_ci    assert not ret, f"\n error: Failed to apply '{patch_file}'"
2583af6ab5fSopenharmony_ci
2593af6ab5fSopenharmony_ci
2603af6ab5fSopenharmony_cidef git_clean(cwd):
2613af6ab5fSopenharmony_ci    cmd = ['git', 'checkout', '--', '.']
2623af6ab5fSopenharmony_ci    run_cmd_cwd(cmd, cwd)
2633af6ab5fSopenharmony_ci
2643af6ab5fSopenharmony_ci
2653af6ab5fSopenharmony_cidef npm_install(cwd):
2663af6ab5fSopenharmony_ci    cmd = ['npm', 'install']
2673af6ab5fSopenharmony_ci    ret = run_cmd_cwd(cmd, cwd)
2683af6ab5fSopenharmony_ci    assert not ret, f"\n error: Failed to 'npm install'"
2693af6ab5fSopenharmony_ci
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_cidef search_dependency(file, directory):
2723af6ab5fSopenharmony_ci    for root, dirs, files in os.walk(directory, topdown=True):
2733af6ab5fSopenharmony_ci        for f in files:
2743af6ab5fSopenharmony_ci            if f == file:
2753af6ab5fSopenharmony_ci                return os.path.join(root, f)
2763af6ab5fSopenharmony_ci    return "FILE_NOT_FOUND"
2773af6ab5fSopenharmony_ci
2783af6ab5fSopenharmony_ci
2793af6ab5fSopenharmony_cidef collect_module_dependencies(file, directory, traversedDependencies):
2803af6ab5fSopenharmony_ci    dependencies = []
2813af6ab5fSopenharmony_ci    traversedDependencies.append(file)
2823af6ab5fSopenharmony_ci    with open(file, 'r', encoding='utf-8') as f:
2833af6ab5fSopenharmony_ci        content = f.read()
2843af6ab5fSopenharmony_ci        module_import_list = re.findall(r'(import|from)(?:\s*)\(?(\'(\.\/.*)\'|"(\.\/.*)")\)?', content)
2853af6ab5fSopenharmony_ci
2863af6ab5fSopenharmony_ci        for result in list(set(module_import_list)):
2873af6ab5fSopenharmony_ci            specifier = (result[2] if len(result[2]) != 0 else result[3]).lstrip('./')
2883af6ab5fSopenharmony_ci            if os.path.basename(file) is not specifier:
2893af6ab5fSopenharmony_ci                dependency = search_dependency(specifier, directory)
2903af6ab5fSopenharmony_ci                if dependency == "FILE_NOT_FOUND":
2913af6ab5fSopenharmony_ci                    continue
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ci                if dependency not in traversedDependencies:
2943af6ab5fSopenharmony_ci                    dependencies.extend(collect_module_dependencies(dependency, directory,
2953af6ab5fSopenharmony_ci                                                                    list(set(traversedDependencies))))
2963af6ab5fSopenharmony_ci                dependencies.append(dependency)
2973af6ab5fSopenharmony_ci
2983af6ab5fSopenharmony_ci    return dependencies