зеркало из https://github.com/dotnet/llilc.git
246 строки
9.8 KiB
Python
246 строки
9.8 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
#title :llilc_runtest.py
|
|
#description :
|
|
#
|
|
# This script runs CoreCLR test with specified LLILC JIT and pre-built
|
|
# CoreCLR runtime. If verbose level is specified, either summary or
|
|
# verbose, a result will be created in default location or a place
|
|
# that is specified. In verbose case, the result will be normalized
|
|
# with filter.
|
|
#
|
|
# It is required to run this script from tests directory in a CoreCLR
|
|
# repository.
|
|
#
|
|
# To exclude undesired test cases, please edit exclusion file.
|
|
#
|
|
# usage: llilc_runtest.py [-h] [-a {x64,x86}] [-b {debug,release}]
|
|
# [-d {summary,verbose}] [-r RESULT_PATH] -j JIT_PATH -c
|
|
# CORECLR_RUNTIME_PATH
|
|
#
|
|
# optional arguments:
|
|
# -h, --help show this help message and exit
|
|
# -a {x64,x86}, --arch {x64,x86}
|
|
# the target architure
|
|
# -b {debug,release}, --build {debug,release}
|
|
# release or debug build of CoreCLR run-time used
|
|
# -d {summary,verbose}, --dump-level {summary,verbose}
|
|
# the dump level: summary, or verbose
|
|
# -r RESULT_PATH, --result-path RESULT_PATH
|
|
# the path to runtest result output directory
|
|
#
|
|
# required arguments:
|
|
# -j JIT_PATH, --jit-path JIT_PATH
|
|
# full path to jit .dll
|
|
# -c CORECLR_RUNTIME_PATH, --coreclr-runtime-path CORECLR_RUNTIME_PATH
|
|
# full path to CoreCLR run-time binary directory
|
|
#
|
|
#==========================================================================================
|
|
|
|
import argparse
|
|
import time
|
|
import os
|
|
import shutil
|
|
import glob
|
|
import sys
|
|
import stat
|
|
import subprocess
|
|
import applyfilter
|
|
import const
|
|
|
|
# Return OS name used internally in paths
|
|
def OSName():
|
|
if os.name == 'nt':
|
|
return 'Windows_NT'
|
|
else:
|
|
return 'Unknown'
|
|
|
|
# Return the path of built test path relavtive to coreclr tests directory
|
|
def BuiltTestPath(arch, build):
|
|
built_test_directory = OSName() + '.' + arch + '.' + build
|
|
built_test_path = os.path.join('..', 'bin', 'tests', built_test_directory)
|
|
return built_test_path
|
|
|
|
# Exculde top level test directories
|
|
def ExcludeTopLevelTestDirectories():
|
|
exclusion = os.path.join(os.path.dirname(__file__), 'exclusion')
|
|
with open(str(exclusion)) as excl:
|
|
content = excl.readlines()
|
|
os.environ['SkipTestAssemblies'] = content[1]
|
|
|
|
# Exclude individual test cases
|
|
def ExcludeIndividualTestCases(path):
|
|
exclusion = os.path.join(os.path.dirname(__file__), 'exclusion')
|
|
with open(str(exclusion)) as excl:
|
|
try:
|
|
glob_files_to_delete = []
|
|
content = excl.read().splitlines()
|
|
for line in range(4, len(content)):
|
|
all = content[line] + '*'
|
|
files_to_delete = os.path.join(path, all)
|
|
glob_files_to_delete.extend(glob.glob(files_to_delete))
|
|
for file_to_delete in glob_files_to_delete:
|
|
os.remove(file_to_delete)
|
|
except OSError:
|
|
pass
|
|
|
|
# Remove unwanted test result files
|
|
def CleanUpResultFiles(path):
|
|
try:
|
|
for root, subdirs, files in os.walk(path):
|
|
for file in files:
|
|
if not file.endswith('error.txt'):
|
|
file_path = os.path.join(root, file)
|
|
os.remove(file_path)
|
|
except OSError:
|
|
pass
|
|
|
|
# Return default result path if result is generated
|
|
def DefaultResultPath():
|
|
default_result_path = os.environ['TEMP']
|
|
default_result_path = os.path.join(default_result_path, 'LLILCTestResult')
|
|
return default_result_path
|
|
|
|
# Remove readonly files
|
|
def del_rw(action, name, exc):
|
|
os.chmod(name, stat.S_IWRITE)
|
|
os.remove(name)
|
|
|
|
# Count files in a directory
|
|
def CountFiles(path, suffix):
|
|
total = 0
|
|
for root, sub_dirs, files in os.walk(path):
|
|
for file_name in files:
|
|
if file_name.endswith(suffix):
|
|
total = total + 1
|
|
return total
|
|
|
|
def main(argv):
|
|
# define return code const value
|
|
const.RunTestFail = 1
|
|
const.RunTestOK = 0
|
|
const.GeneralError = -1
|
|
const.UnknownArguments = -2
|
|
const.NormalizationFail = -3
|
|
const.WrongRunDir = -4
|
|
|
|
# Parse the command line
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-a', '--arch', type=str, choices={'x86', 'x64'},
|
|
default='x64', help='the target architure')
|
|
parser.add_argument('-b', '--build', type=str, choices={'release', 'debug'},
|
|
default='debug', help='release or debug build of CoreCLR run-time used')
|
|
parser.add_argument('-d', '--dump-level', type=str, choices={'summary', 'verbose'},
|
|
help='the dump level: summary, or verbose')
|
|
parser.add_argument('-r', '--result-path', type=str,
|
|
default=DefaultResultPath(), help='the path to runtest result output directory')
|
|
required = parser.add_argument_group('required arguments')
|
|
required.add_argument('-j', '--jit-path', required=True,
|
|
help='full path to jit .dll')
|
|
required.add_argument('-c', '--coreclr-runtime-path', required=True,
|
|
help='full path to CoreCLR run-time binary directory')
|
|
args, unknown = parser.parse_known_args(argv)
|
|
|
|
if unknown:
|
|
print('Unknown argument(s): ', ', '.join(unknown))
|
|
return const.UnknowArguments
|
|
|
|
# Ensure the command run from a CoreCLR tests directory
|
|
current_work_directory = os.getcwd()
|
|
path, folder = os.path.split(current_work_directory)
|
|
parent_path, parent_folder = os.path.split(path)
|
|
if (not folder == 'tests' or
|
|
not parent_folder == 'coreclr'):
|
|
print('This script is required to run from tests directory in a CoreCLR repository.' )
|
|
return const.WrongRunDir
|
|
|
|
try:
|
|
# Determine the built test location
|
|
build_test_path = BuiltTestPath(str(args.arch), str(args.build))
|
|
|
|
# Determine time stamp
|
|
time_stamp = str(time.time()).split('.')[0]
|
|
|
|
# Copy in llilcjit.dll with time stamp
|
|
time_stamped_jit_name = 'LLILCJit' + time_stamp + '.dll'
|
|
time_stamped_jit_path = os.path.join(args.coreclr_runtime_path, time_stamped_jit_name)
|
|
shutil.copy2(args.jit_path, time_stamped_jit_path)
|
|
|
|
# Create llilctestenv.cmd with time stamp
|
|
time_stamped_test_env_name = 'LLILCTestEnv' + time_stamp + '.cmd'
|
|
time_stamped_test_env_path = os.path.join(args.coreclr_runtime_path, time_stamped_test_env_name)
|
|
|
|
# Todo: Test Env is right now only for Windows. Will expand when cross platform
|
|
with open(time_stamped_test_env_path, 'w') as test_env:
|
|
test_env.write('set COMPlus_AltJit=*\n')
|
|
test_env.write('set COMPlus_AltJitName=' + time_stamped_jit_name + '\n')
|
|
test_env.write('set COMPlus_GCConservative=1\n')
|
|
test_env.write('chcp 65001\n')
|
|
if args.dump_level is not None:
|
|
test_env.write('set COMPlus_DumpLLVMIR=' + args.dump_level + '\n')
|
|
|
|
# Exclude undesired tests from running
|
|
ExcludeTopLevelTestDirectories()
|
|
ExcludeIndividualTestCases(build_test_path)
|
|
except:
|
|
e = sys.exc_info()[0]
|
|
print('Error: RunTest failed due to ', e)
|
|
return const.GeneralError
|
|
|
|
# Run the test
|
|
return_code = const.RunTestOK
|
|
runtest_command = 'runtest ' + args.arch + ' ' + args.build
|
|
runtest_command = runtest_command + ' Testenv ' + time_stamped_test_env_path
|
|
runtest_command = runtest_command + ' ' + args.coreclr_runtime_path
|
|
print(runtest_command)
|
|
error_level = subprocess.call(runtest_command, shell=True)
|
|
if error_level == 1:
|
|
return_code = const.RunTestFail
|
|
|
|
# Remove temporary time-stamped jit and test env files
|
|
try:
|
|
os.remove(time_stamped_jit_path)
|
|
os.remove(time_stamped_test_env_path)
|
|
except:
|
|
e = sys.exc_info()[0]
|
|
print('Error: RunTest failed due to ', e)
|
|
return const.GeneralError
|
|
|
|
# Copy out result if there is one, clean up undesired files,
|
|
# In case of verbose result, normalize it and extract out summary.
|
|
# In case of summary result, rename all result file name.
|
|
if args.dump_level is not None:
|
|
try:
|
|
coreclr_result_path = os.path.join(build_test_path, 'Reports')
|
|
if os.path.exists(args.result_path):
|
|
shutil.rmtree(args.result_path, onerror=del_rw)
|
|
shutil.copytree(coreclr_result_path, args.result_path)
|
|
ExcludeIndividualTestCases(args.result_path)
|
|
CleanUpResultFiles(args.result_path)
|
|
total = CountFiles(args.result_path, 'error.txt')
|
|
if args.dump_level == 'verbose':
|
|
print('Verbose-mode post-processing started')
|
|
print('found ', total, 'valid raw test outputs (error.txt) under ', str(coreclr_result_path))
|
|
print('creating normalized outputs (error.txt) under ', str(args.result_path))
|
|
print('creating summary outputs (sum.txt) under ', str(args.result_path))
|
|
applyfilter.ApplyAll(args.result_path)
|
|
print('Verbose-mode post-processing finished')
|
|
if args.dump_level == 'summary':
|
|
print('Summary-mode post-processing started')
|
|
print('found ', total, 'valid raw test outputs (error.txt) under ', os.path.abspath(coreclr_result_path))
|
|
print('creating summary outputs (sum.txt) under ', str(args.result_path))
|
|
applyfilter.SummaryRenameAll(args.result_path)
|
|
print('Summary-mode post-processing finished')
|
|
except:
|
|
e = sys.exc_info()[0]
|
|
print('Error: Test result normalization failed due to ', e)
|
|
return const.NormalizationFail
|
|
else:
|
|
print('No post-processing needed.')
|
|
|
|
return return_code
|
|
|
|
if __name__ == '__main__':
|
|
return_code = main(sys.argv[1:])
|
|
sys.exit(return_code)
|