1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# 4# Copyright (c) 2024 Huawei Device Co., Ltd. 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17import multiprocessing.pool 18import os 19import sys 20from distutils.dir_util import copy_tree 21import random 22from typing import Tuple, Dict, Final, List 23import logging 24 25import stress_test 26import stress_common 27from stress_test import StressTest, Test, Result 28 29from stress_common import SCRIPT_DIR, TMP_DIR, collect_from 30 31TEST_ETS_SOURCES_ROOT = os.path.join(SCRIPT_DIR, '..', '..', '..', 32 'static_core', 'plugins', "ets", "tests", 33 'ets_func_tests') 34STDLIB_ETS_SOURCES_ROOT = os.path.join(SCRIPT_DIR, '..', '..', '..', 35 'static_core', 'plugins', "ets", 36 "stdlib") 37 38 39def get_stdlib_path(build_dir: str) -> str: 40 return os.path.join( 41 build_dir, 42 'gen/arkcompiler/runtime_core/static_core/plugins/ets/etsstdlib.abc') 43 44 45def get_verifier_path(build_dir: str) -> str: 46 return os.path.abspath( 47 os.path.join(build_dir, f'arkcompiler/runtime_core/verifier')) 48 49 50def get_config_path(build_dir: str) -> str: 51 return f'{build_dir}/arkcompiler/ets_frontend/arktsconfig.json' 52 53 54def stress_single(test: Test, out_dir) -> Result: 55 stress_abc = test.abc + '.stress.abc' 56 result = stress_common.run_abckit(out_dir, test.source, test.abc, 57 stress_abc) 58 59 if result.returncode == 0: 60 return Result(test.source, 0) 61 return Result(test.source, result.returncode, result.stdout, result.stderr) 62 63 64class StsStressTest(StressTest): 65 66 def __init__(self, args): 67 super().__init__() 68 self.ets_dir = os.path.join(TMP_DIR, 'abckit_test_ets') 69 self.stdlib_dir = os.path.join(TMP_DIR, 'abckit_stdlib') 70 71 self.cp = self.get_compiler_path(args.build_dir) 72 self.vp = get_verifier_path(args.build_dir) 73 self.sp = get_stdlib_path(args.build_dir) 74 self.config = get_config_path(args.build_dir) 75 self.build_dir = args.build_dir 76 77 rc_lib_path: Final[str] = f'{args.build_dir}/arkcompiler/runtime_core' 78 79 self.cenv: Dict[str, str] = {'LD_LIBRARY_PATH': rc_lib_path} 80 self.venv: Dict[str, str] = { 81 'LD_LIBRARY_PATH': 82 f'{rc_lib_path}:{args.build_dir}/thirdparty/icu/' 83 } 84 85 def get_fail_list_path(self) -> str: 86 return os.path.join(SCRIPT_DIR, 'fail_list_sts.json') 87 88 def run_single(self, test: Test) -> Result: 89 stress_result: Result = stress_single(test, self.build_dir) 90 verify_result_one: Result = self.verify_single(test) 91 92 r2p = Test(test.source, test.abc + ".stress.abc") 93 verify_result_two: Result = self.verify_single(r2p) 94 95 if stress_result.result != 0: 96 error = stress_common.parse_stdout(stress_result.result, 97 stress_result.stdout) 98 return Result(test.source, error) 99 # Stress test passed 100 101 if verify_result_two.result == 0: 102 return Result(test.source, "0") 103 104 if verify_result_one.result != verify_result_two.result: 105 msg = f'Verifier result changed. Was {verify_result_one.result}, now {verify_result_two.result}' 106 return Result(test.source, msg) 107 108 return Result(test.source, "0") 109 110 def prepare(self) -> None: 111 self.download_ets() 112 self.download_stdlib() 113 114 def download_ets(self) -> None: 115 logger = stress_common.create_logger() 116 abs_path = os.path.abspath(TEST_ETS_SOURCES_ROOT) 117 logger.debug('Ets test download from %s', abs_path) 118 if not os.path.exists(abs_path): 119 logger.debug('Not exists %s', abs_path) 120 return 121 copy_tree(abs_path, self.ets_dir) 122 123 def download_stdlib(self) -> None: 124 logger = stress_common.create_logger() 125 126 abs_path = os.path.abspath(STDLIB_ETS_SOURCES_ROOT) 127 logger.debug('Stdlib download from %s', abs_path) 128 if not os.path.exists(abs_path): 129 logger.debug('Not exists %s', abs_path) 130 return 131 copy_tree(abs_path, self.stdlib_dir) 132 133 def get_compiler_path(self, build_dir) -> str: 134 return os.path.abspath( 135 os.path.join(build_dir, 'arkcompiler/ets_frontend/es2panda')) 136 137 def compile_single(self, src: str) -> Tuple[str, str, int]: 138 logger = stress_common.create_logger() 139 abc_path = src + '.abc' 140 cmd = [ 141 self.cp, '--ets-module', '--arktsconfig', self.config, 142 f'--output={abc_path}', src 143 ] 144 result = stress_common.stress_exec(cmd, 145 allow_error=True, 146 print_command=True, 147 env=self.cenv) 148 if result.returncode == 0 and not os.path.exists(abc_path): 149 logger.debug( 150 'WARNING: for %s es2abc has %s return code, but has no output', 151 src, result.returncode) 152 return src, abc_path, result.returncode 153 154 def verify_single(self, test: Test) -> Result: 155 boot_panda_files = f'--boot-panda-files={self.sp}' 156 cmd = [self.vp, boot_panda_files, '--load-runtimes=ets', test.abc] 157 result = stress_common.stress_exec(cmd, 158 allow_error=True, 159 print_command=True, 160 env=self.venv) 161 return Result(test.source, result.returncode) 162 163 def collect(self) -> List[str]: 164 logger = stress_common.create_logger() 165 tests: List[str] = [] 166 tests.extend( 167 collect_from( 168 self.ets_dir, lambda name: name.endswith('.sts') and not name. 169 startswith('.'))) 170 tests.extend( 171 collect_from( 172 self.stdlib_dir, lambda name: name.endswith('.sts') and 173 not name.startswith('.'))) 174 175 random.shuffle(tests) 176 logger.debug('Total tests: %s', len(tests)) 177 return tests 178