test system
This commit is contained in:
570
run_tests.py
570
run_tests.py
@@ -1,165 +1,37 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2013, Intel Corporation
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# test-running driver for ispc
|
||||
|
||||
from optparse import OptionParser
|
||||
import multiprocessing
|
||||
from ctypes import c_int
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import re
|
||||
import signal
|
||||
import random
|
||||
import string
|
||||
import subprocess
|
||||
import shlex
|
||||
import platform
|
||||
import tempfile
|
||||
import os.path
|
||||
import time
|
||||
|
||||
# disable fancy error/warning printing with ANSI colors, so grepping for error
|
||||
# messages doesn't get confused
|
||||
os.environ["TERM"] = "dumb"
|
||||
|
||||
# This script is affected by http://bugs.python.org/issue5261 on OSX 10.5 Leopard
|
||||
# git history has a workaround for that issue.
|
||||
|
||||
is_windows = (platform.system() == 'Windows' or
|
||||
'CYGWIN_NT' in platform.system())
|
||||
|
||||
parser = OptionParser()
|
||||
parser.add_option("-r", "--random-shuffle", dest="random", help="Randomly order tests",
|
||||
default=False, action="store_true")
|
||||
parser.add_option("-g", "--generics-include", dest="include_file", help="Filename for header implementing functions for generics",
|
||||
default=None)
|
||||
parser.add_option("-f", "--ispc-flags", dest="ispc_flags", help="Additional flags for ispc (-g, -O1, ...)",
|
||||
default="")
|
||||
parser.add_option('-t', '--target', dest='target',
|
||||
help='Set compilation target (sse2-i32x4, sse2-i32x8, sse4-i32x4, sse4-i32x8, sse4-i16x8, sse4-i8x16, avx1-i32x8, avx1-i32x16, avx1.1-i32x8, avx1.1-i32x16, avx2-i32x8, avx2-i32x16, generic-x1, generic-x4, generic-x8, generic-x16, generic-x32, generic-x64)',
|
||||
default="sse4")
|
||||
parser.add_option('-a', '--arch', dest='arch',
|
||||
help='Set architecture (arm, x86, x86-64)',
|
||||
default="x86-64")
|
||||
parser.add_option("-c", "--compiler", dest="compiler_exe", help="Compiler binary to use to run tests",
|
||||
default=None)
|
||||
parser.add_option('-o', '--no-opt', dest='no_opt', help='Disable optimization',
|
||||
default=False, action="store_true")
|
||||
parser.add_option('-j', '--jobs', dest='num_jobs', help='Maximum number of jobs to run in parallel',
|
||||
default="1024", type="int")
|
||||
parser.add_option('-v', '--verbose', dest='verbose', help='Enable verbose output',
|
||||
default=False, action="store_true")
|
||||
parser.add_option('--wrap-exe', dest='wrapexe',
|
||||
help='Executable to wrap test runs with (e.g. "valgrind")',
|
||||
default="")
|
||||
parser.add_option('--time', dest='time', help='Enable time output',
|
||||
default=False, action="store_true")
|
||||
parser.add_option('--non-interactive', dest='non_interactive', help='Disable interactive status updates',
|
||||
default=False, action="store_true")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if options.target == 'neon':
|
||||
options.arch = 'arm'
|
||||
|
||||
# use relative path to not depend on host directory, which may possibly
|
||||
# have white spaces and unicode characters.
|
||||
if not is_windows:
|
||||
ispc_exe = "./ispc"
|
||||
else:
|
||||
ispc_exe = ".\\Release\\ispc.exe"
|
||||
|
||||
# checks the required ispc compiler otherwise prints an error message
|
||||
if not os.path.exists(ispc_exe):
|
||||
sys.stderr.write("Fatal error: missing ispc compiler: %s\n" % ispc_exe)
|
||||
sys.exit()
|
||||
|
||||
ispc_exe += " " + options.ispc_flags
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.stdout.write("ispc compiler: %s\n" % ispc_exe)
|
||||
|
||||
is_generic_target = (options.target.find("generic-") != -1 and
|
||||
options.target != "generic-1")
|
||||
if is_generic_target and options.include_file == None:
|
||||
if options.target == "generic-4":
|
||||
sys.stderr.write("No generics #include specified; using examples/intrinsics/sse4.h\n")
|
||||
options.include_file = "examples/intrinsics/sse4.h"
|
||||
elif options.target == "generic-8":
|
||||
sys.stderr.write("No generics #include specified and no default available for \"generic-8\" target.\n")
|
||||
sys.exit(1)
|
||||
elif options.target == "generic-16":
|
||||
sys.stderr.write("No generics #include specified; using examples/intrinsics/generic-16.h\n")
|
||||
options.include_file = "examples/intrinsics/generic-16.h"
|
||||
elif options.target == "generic-32":
|
||||
sys.stderr.write("No generics #include specified; using examples/intrinsics/generic-32.h\n")
|
||||
options.include_file = "examples/intrinsics/generic-32.h"
|
||||
elif options.target == "generic-64":
|
||||
sys.stderr.write("No generics #include specified; using examples/intrinsics/generic-64.h\n")
|
||||
options.include_file = "examples/intrinsics/generic-64.h"
|
||||
|
||||
if options.compiler_exe == None:
|
||||
if is_windows:
|
||||
options.compiler_exe = "cl.exe"
|
||||
else:
|
||||
options.compiler_exe = "g++"
|
||||
|
||||
# checks the required compiler otherwise prints an error message
|
||||
PATH_dir = string.split(os.getenv("PATH"), os.pathsep)
|
||||
compiler_exists = False
|
||||
|
||||
for counter in PATH_dir:
|
||||
if os.path.exists(counter + os.sep + options.compiler_exe):
|
||||
compiler_exists = True
|
||||
break
|
||||
|
||||
if not compiler_exists:
|
||||
sys.stderr.write("Fatal error: missing the required compiler: %s \n" %
|
||||
options.compiler_exe)
|
||||
sys.exit()
|
||||
|
||||
ispc_root = "."
|
||||
|
||||
# if no specific test files are specified, run all of the tests in tests/,
|
||||
# failing_tests/, and tests_errors/
|
||||
if len(args) == 0:
|
||||
files = glob.glob(ispc_root + os.sep + "tests" + os.sep + "*ispc") + \
|
||||
glob.glob(ispc_root + os.sep + "failing_tests" + os.sep + "*ispc") + \
|
||||
glob.glob(ispc_root + os.sep + "tests_errors" + os.sep + "*ispc")
|
||||
else:
|
||||
if is_windows:
|
||||
argfiles = [ ]
|
||||
for f in args:
|
||||
# we have to glob ourselves if this is being run under a DOS
|
||||
# shell, as it passes wildcard as is.
|
||||
argfiles += glob.glob(f)
|
||||
else:
|
||||
argfiles = args
|
||||
|
||||
files = [ ]
|
||||
for f in argfiles:
|
||||
if os.path.splitext(string.lower(f))[1] != ".ispc":
|
||||
sys.stdout.write("Ignoring file %s, which doesn't have an .ispc extension.\n" % f)
|
||||
else:
|
||||
files += [ f ]
|
||||
|
||||
# max_test_length is used to issue exact number of whitespace characters when
|
||||
# updating status. Otherwise update causes new lines standard 80 char terminal
|
||||
# on both Linux and Windows.
|
||||
max_test_length = 0
|
||||
for f in files:
|
||||
max_test_length = max(max_test_length, len(f))
|
||||
|
||||
# randomly shuffle the tests if asked to do so
|
||||
if (options.random):
|
||||
random.seed()
|
||||
random.shuffle(files)
|
||||
|
||||
# counter
|
||||
total_tests = 0
|
||||
|
||||
|
||||
# utility routine to print an update on the number of tests that have been
|
||||
# finished. Should be called with the lock held..
|
||||
def update_progress(fn, total_tests_arg, counter, max_test_length_arg):
|
||||
@@ -176,7 +48,7 @@ def update_progress(fn, total_tests_arg, counter, max_test_length_arg):
|
||||
|
||||
def run_command(cmd):
|
||||
if options.verbose:
|
||||
sys.stdout.write("Running: %s\n" % cmd)
|
||||
print_debug("Running: %s\n" % cmd, s, run_tests_log)
|
||||
|
||||
# Here's a bit tricky part. To pass a command for execution we should
|
||||
# break down the line in to arguments. shlex class is designed exactly
|
||||
@@ -204,9 +76,9 @@ def run_cmds(compile_cmds, run_cmd, filename, expect_failure):
|
||||
(return_code, output) = run_command(cmd)
|
||||
compile_failed = (return_code != 0)
|
||||
if compile_failed:
|
||||
sys.stdout.write("Compilation of test %s failed \n" % filename)
|
||||
print_debug("Compilation of test %s failed \n" % filename, s, run_tests_log)
|
||||
if output != "":
|
||||
sys.stdout.write("%s" % output.encode("utf-8"))
|
||||
print_debug("%s" % output.encode("utf-8"), s, run_tests_log)
|
||||
return (1, 0)
|
||||
|
||||
(return_code, output) = run_command(run_cmd)
|
||||
@@ -215,11 +87,11 @@ def run_cmds(compile_cmds, run_cmd, filename, expect_failure):
|
||||
surprise = ((expect_failure and not run_failed) or
|
||||
(not expect_failure and run_failed))
|
||||
if surprise == True:
|
||||
sys.stderr.write("Test %s %s (return code %d) \n" % \
|
||||
print_debug("Test %s %s (return code %d) \n" % \
|
||||
(filename, "unexpectedly passed" if expect_failure else "failed",
|
||||
return_code))
|
||||
return_code), s, run_tests_log)
|
||||
if output != "":
|
||||
sys.stdout.write("%s\n" % output.encode("utf-8"))
|
||||
print_debug("%s\n" % output.encode("utf-8"), s, run_tests_log)
|
||||
if surprise == True:
|
||||
return (0, 1)
|
||||
else:
|
||||
@@ -298,11 +170,11 @@ def run_test(testname):
|
||||
file.close()
|
||||
|
||||
if re.search(firstline, output) == None:
|
||||
sys.stderr.write("Didn't see expected error message %s from test %s.\nActual output:\n%s\n" % \
|
||||
(firstline, testname, output))
|
||||
print_debug("Didn't see expected error message %s from test %s.\nActual output:\n%s\n" % \
|
||||
(firstline, testname, output), s, run_tests_log)
|
||||
return (1, 0)
|
||||
elif got_error == False:
|
||||
sys.stderr.write("Unexpectedly no errors issued from test %s\n" % testname)
|
||||
print_debug("Unexpectedly no errors issued from test %s\n" % testname, s, run_tests_log)
|
||||
return (1, 0)
|
||||
else:
|
||||
return (0, 0)
|
||||
@@ -328,8 +200,7 @@ def run_test(testname):
|
||||
break
|
||||
file.close()
|
||||
if match == -1:
|
||||
sys.stderr.write("Fatal error: unable to find function signature " + \
|
||||
"in test %s\n" % testname)
|
||||
error("unable to find function signature in test %s\n" % testname, 0)
|
||||
return (1, 0)
|
||||
else:
|
||||
global is_generic_target
|
||||
@@ -404,7 +275,21 @@ def run_test(testname):
|
||||
# pull tests to run from the given queue and run them. Multiple copies of
|
||||
# this function will be running in parallel across all of the CPU cores of
|
||||
# the system.
|
||||
def run_tasks_from_queue(queue, queue_ret, queue_skip, total_tests_arg, max_test_length_arg, counter, mutex):
|
||||
def run_tasks_from_queue(queue, queue_ret, queue_skip, total_tests_arg, max_test_length_arg, counter, mutex, glob_var):
|
||||
# This is needed on windows because windows doen't copy globals from parent process whili multiprocessing
|
||||
global is_windows
|
||||
is_windows = glob_var[0]
|
||||
global options
|
||||
options = glob_var[1]
|
||||
global s
|
||||
s = glob_var[2]
|
||||
global ispc_exe
|
||||
ispc_exe = glob_var[3]
|
||||
global is_generic_target
|
||||
is_generic_target = glob_var[4]
|
||||
global run_tests_log
|
||||
run_tests_log = glob_var[5]
|
||||
|
||||
if is_windows:
|
||||
tmpdir = "tmp%d" % os.getpid()
|
||||
os.mkdir(tmpdir)
|
||||
@@ -454,7 +339,256 @@ def sigint(signum, frame):
|
||||
t.terminate()
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
def file_check(compfails, runfails):
|
||||
errors = len(compfails) + len(runfails)
|
||||
new_compfails = []
|
||||
new_runfails = []
|
||||
new_passes_compfails = []
|
||||
new_passes_runfails = []
|
||||
# Open file fail_db.txt
|
||||
f = open(test_states, 'r')
|
||||
f_lines = f.readlines()
|
||||
f.close()
|
||||
# Detect OS
|
||||
if platform.system() == 'Windows' or 'CYGWIN_NT' in platform.system():
|
||||
OS = "Windows"
|
||||
else:
|
||||
if platform.system() == 'Darwin':
|
||||
OS = "Mac"
|
||||
else:
|
||||
OS = "Linux"
|
||||
# Detect opt_set
|
||||
if options.no_opt == True:
|
||||
opt = "-O0"
|
||||
else:
|
||||
opt = "-O2"
|
||||
# Detect LLVM version
|
||||
temp1 = common.detect_version(ispc_exe + " --version")
|
||||
llvm_version = temp1[-10:-2]
|
||||
#Detect compiler version
|
||||
if is_windows == False:
|
||||
temp1 = common.detect_version(options.compiler_exe + " --version")
|
||||
temp2 = temp1.split(" ")
|
||||
compiler_version = temp2[0] + temp2[2][0:4]
|
||||
else:
|
||||
compiler_version = "cl"
|
||||
new_line = " "+options.arch.rjust(6)+" "+options.target.rjust(14)+" "+OS.rjust(7)+" "+llvm_version+" "+compiler_version.rjust(10)+" "+opt+" *\n"
|
||||
|
||||
new_compfails = compfails[:]
|
||||
new_runfails = runfails[:]
|
||||
new_f_lines = f_lines[:]
|
||||
for j in range(0, len(f_lines)):
|
||||
if (((" "+options.arch+" ") in f_lines[j]) and
|
||||
((" "+options.target+" ") in f_lines[j]) and
|
||||
((" "+OS+" ") in f_lines[j]) and
|
||||
((" "+llvm_version+" ") in f_lines[j]) and
|
||||
((" "+compiler_version+" ") in f_lines[j]) and
|
||||
((" "+opt+" ") in f_lines[j])):
|
||||
if (" compfail " in f_lines[j]):
|
||||
f = 0
|
||||
for i in range(0, len(compfails)):
|
||||
if compfails[i] in f_lines[j]:
|
||||
new_compfails.remove(compfails[i])
|
||||
else:
|
||||
f = f + 1
|
||||
if f == len(compfails):
|
||||
temp3 = f_lines[j].split(" ")
|
||||
new_passes_compfails.append(temp3[0])
|
||||
if options.update == "FP":
|
||||
new_f_lines.remove(f_lines[j])
|
||||
if (" runfail " in f_lines[j]):
|
||||
f = 0
|
||||
for i in range(0, len(runfails)):
|
||||
if runfails[i] in f_lines[j]:
|
||||
new_runfails.remove(runfails[i])
|
||||
else:
|
||||
f = f + 1
|
||||
if f == len(runfails):
|
||||
temp3 = f_lines[j].split(" ")
|
||||
new_passes_runfails.append(temp3[0])
|
||||
if options.update == "FP":
|
||||
new_f_lines.remove(f_lines[j])
|
||||
if len(new_runfails) != 0:
|
||||
print_debug("NEW RUNFAILS:\n", s, run_tests_log)
|
||||
for i in range (0,len(new_runfails)):
|
||||
new_f_lines.append(new_runfails[i] + " runfail " + new_line)
|
||||
print_debug("\t" + new_runfails[i] + "\n", s, run_tests_log)
|
||||
if len(new_compfails) != 0:
|
||||
print_debug("NEW COMPFAILS:\n", s, run_tests_log)
|
||||
for i in range (0,len(new_compfails)):
|
||||
new_f_lines.append(new_compfails[i] + " compfail " + new_line)
|
||||
print_debug("\t" + new_compfails[i] + "\n", s, run_tests_log)
|
||||
if len(new_passes_runfails) != 0:
|
||||
print_debug("NEW PASSES after RUNFAILS:\n", s, run_tests_log)
|
||||
for i in range (0,len(new_passes_runfails)):
|
||||
print_debug("\t" + new_passes_runfails[i] + "\n", s, run_tests_log)
|
||||
if len(new_passes_compfails) != 0:
|
||||
print_debug("NEW PASSES after COMPFAILS:\n", s, run_tests_log)
|
||||
for i in range (0,len(new_passes_compfails)):
|
||||
print_debug("\t" + new_passes_compfails[i] + "\n", s, run_tests_log)
|
||||
|
||||
if options.update != "":
|
||||
output = open(test_states, 'w')
|
||||
output.writelines(new_f_lines)
|
||||
output.close()
|
||||
return [new_runfails, new_compfails, new_passes_runfails, new_passes_compfails, new_line, errors]
|
||||
|
||||
def verify():
|
||||
# Open file fail_db.txt
|
||||
f = open(test_states, 'r')
|
||||
f_lines = f.readlines()
|
||||
f.close()
|
||||
check = [["g++", "clang", "cl"],["-O0", "-O2"],["x86","x86-64"],
|
||||
["Linux","Windows","Mac"],["LLVM 3.1","LLVM 3.2","LLVM 3.3","LLVM head"],
|
||||
["sse2-i32x4", "sse2-i32x8", "sse4-i32x4", "sse4-i32x8", "sse4-i16x8",
|
||||
"sse4-i8x16", "avx1-i32x8", "avx1-i32x16", "avx1.1-i32x8", "avx1.1-i32x16",
|
||||
"avx2-i32x8", "avx2-i32x16", "generic-1", "generic-4", "generic-8",
|
||||
"generic-16", "generic-32", "generic-64"]]
|
||||
for i in range (0,len(f_lines)):
|
||||
if f_lines[i][0] == "%":
|
||||
continue
|
||||
for j in range(0,len(check)):
|
||||
temp = 0
|
||||
for t in range(0,len(check[j])):
|
||||
if " " + check[j][t] + " " in f_lines[i]:
|
||||
temp = temp + 1
|
||||
if temp != 1:
|
||||
print_debug("error in line " + str(i) + "\n", False, run_tests_log)
|
||||
break
|
||||
|
||||
|
||||
def run_tests(options1, args, print_version):
|
||||
global options
|
||||
options = options1
|
||||
global s
|
||||
s = options.silent
|
||||
|
||||
# prepare run_tests_log and test_states files
|
||||
global run_tests_log
|
||||
if options.in_file:
|
||||
run_tests_log = os.getcwd() + os.sep + options.in_file
|
||||
if print_version == 1:
|
||||
common.remove_if_exists(run_tests_log)
|
||||
else:
|
||||
run_tests_log = ""
|
||||
global test_states
|
||||
test_states = "fail_db.txt"
|
||||
if options.verify:
|
||||
verify()
|
||||
return 0
|
||||
|
||||
# disable fancy error/warning printing with ANSI colors, so grepping for error
|
||||
# messages doesn't get confused
|
||||
os.environ["TERM"] = "dumb"
|
||||
|
||||
# This script is affected by http://bugs.python.org/issue5261 on OSX 10.5 Leopard
|
||||
# git history has a workaround for that issue.
|
||||
global is_windows
|
||||
is_windows = (platform.system() == 'Windows' or
|
||||
'CYGWIN_NT' in platform.system())
|
||||
|
||||
if options.target == 'neon':
|
||||
options.arch = 'arm'
|
||||
|
||||
# use relative path to not depend on host directory, which may possibly
|
||||
# have white spaces and unicode characters.
|
||||
global ispc_exe
|
||||
if not is_windows:
|
||||
ispc_exe = "./ispc"
|
||||
else:
|
||||
ispc_exe = ".\\Release\\ispc.exe"
|
||||
|
||||
# checks the required ispc compiler otherwise prints an error message
|
||||
if not os.path.exists(ispc_exe):
|
||||
error("missing ispc compiler: %s\n" % ispc_exe, 1)
|
||||
ispc_exe += " " + options.ispc_flags
|
||||
print_debug("ispc compiler: %s\n" % ispc_exe, s, run_tests_log)
|
||||
|
||||
global is_generic_target
|
||||
is_generic_target = (options.target.find("generic-") != -1 and
|
||||
options.target != "generic-1" and options.target != "generic-x1")
|
||||
if is_generic_target and options.include_file == None:
|
||||
if options.target == "generic-4" or options.target == "generic-x4":
|
||||
error("No generics #include specified; using examples/intrinsics/sse4.h\n", 2)
|
||||
options.include_file = "examples/intrinsics/sse4.h"
|
||||
options.target = "generic-4"
|
||||
elif options.target == "generic-8" or options.target == "generic-x8":
|
||||
error("No generics #include specified and no default available for \"generic-8\" target.\n", 1)
|
||||
options.target = "generic-8"
|
||||
elif options.target == "generic-16" or options.target == "generic-x16":
|
||||
error("No generics #include specified; using examples/intrinsics/generic-16.h\n", 2)
|
||||
options.include_file = "examples/intrinsics/generic-16.h"
|
||||
options.target = "generic-16"
|
||||
elif options.target == "generic-32" or options.target == "generic-x32":
|
||||
error("No generics #include specified; using examples/intrinsics/generic-32.h\n", 2)
|
||||
options.include_file = "examples/intrinsics/generic-32.h"
|
||||
options.target = "generic-32"
|
||||
elif options.target == "generic-64" or options.target == "generic-x64":
|
||||
error("No generics #include specified; using examples/intrinsics/generic-64.h\n", 2)
|
||||
options.include_file = "examples/intrinsics/generic-64.h"
|
||||
options.target = "generic-64"
|
||||
|
||||
if options.compiler_exe == None:
|
||||
if is_windows:
|
||||
options.compiler_exe = "cl.exe"
|
||||
else:
|
||||
options.compiler_exe = "g++"
|
||||
|
||||
# checks the required compiler otherwise prints an error message
|
||||
PATH_dir = string.split(os.getenv("PATH"), os.pathsep)
|
||||
compiler_exists = False
|
||||
|
||||
for counter in PATH_dir:
|
||||
if os.path.exists(counter + os.sep + options.compiler_exe):
|
||||
compiler_exists = True
|
||||
break
|
||||
|
||||
if not compiler_exists:
|
||||
error("missing the required compiler: %s \n" % options.compiler_exe, 1)
|
||||
|
||||
# print compilers versions
|
||||
if print_version > 0:
|
||||
common.print_version(ispc_exe, "", options.compiler_exe, False, run_tests_log, is_windows)
|
||||
|
||||
ispc_root = "."
|
||||
|
||||
# if no specific test files are specified, run all of the tests in tests/,
|
||||
# failing_tests/, and tests_errors/
|
||||
if len(args) == 0:
|
||||
files = glob.glob(ispc_root + os.sep + "tests" + os.sep + "*ispc") + \
|
||||
glob.glob(ispc_root + os.sep + "failing_tests" + os.sep + "*ispc") + \
|
||||
glob.glob(ispc_root + os.sep + "tests_errors" + os.sep + "*ispc")
|
||||
else:
|
||||
if is_windows:
|
||||
argfiles = [ ]
|
||||
for f in args:
|
||||
# we have to glob ourselves if this is being run under a DOS
|
||||
# shell, as it passes wildcard as is.
|
||||
argfiles += glob.glob(f)
|
||||
else:
|
||||
argfiles = args
|
||||
|
||||
files = [ ]
|
||||
for f in argfiles:
|
||||
if os.path.splitext(string.lower(f))[1] != ".ispc":
|
||||
error("Ignoring file %s, which doesn't have an .ispc extension.\n" % f, 2)
|
||||
else:
|
||||
files += [ f ]
|
||||
|
||||
# max_test_length is used to issue exact number of whitespace characters when
|
||||
# updating status. Otherwise update causes new lines standard 80 char terminal
|
||||
# on both Linux and Windows.
|
||||
max_test_length = 0
|
||||
for f in files:
|
||||
max_test_length = max(max_test_length, len(f))
|
||||
|
||||
# randomly shuffle the tests if asked to do so
|
||||
if (options.random):
|
||||
random.seed()
|
||||
random.shuffle(files)
|
||||
|
||||
# counter
|
||||
total_tests = len(files)
|
||||
|
||||
compile_error_files = [ ]
|
||||
@@ -463,7 +597,7 @@ if __name__ == '__main__':
|
||||
|
||||
nthreads = min(multiprocessing.cpu_count(), options.num_jobs)
|
||||
nthreads = min(nthreads, len(files))
|
||||
sys.stdout.write("Running %d jobs in parallel. Running %d tests.\n" % (nthreads, total_tests))
|
||||
print_debug("Running %d jobs in parallel. Running %d tests.\n" % (nthreads, total_tests), s, run_tests_log)
|
||||
|
||||
# put each of the test filenames into a queue
|
||||
q = multiprocessing.Queue()
|
||||
@@ -483,8 +617,10 @@ if __name__ == '__main__':
|
||||
|
||||
start_time = time.time()
|
||||
# launch jobs to run tests
|
||||
glob_var = [is_windows, options, s, ispc_exe, is_generic_target, run_tests_log]
|
||||
for x in range(nthreads):
|
||||
t = multiprocessing.Process(target=run_tasks_from_queue, args=(q, qret, qskip, total_tests, max_test_length, finished_tests_counter, finished_tests_counter_lock))
|
||||
t = multiprocessing.Process(target=run_tasks_from_queue, args=(q, qret, qskip, total_tests,
|
||||
max_test_length, finished_tests_counter, finished_tests_counter_lock, glob_var))
|
||||
task_threads.append(t)
|
||||
t.start()
|
||||
|
||||
@@ -493,35 +629,97 @@ if __name__ == '__main__':
|
||||
for t in task_threads:
|
||||
t.join()
|
||||
if options.non_interactive == False:
|
||||
sys.stdout.write("\n")
|
||||
print_debug("\n", s, run_tests_log)
|
||||
|
||||
elapsed_time = time.time() - start_time
|
||||
|
||||
while not qret.empty():
|
||||
(c, r, s) = qret.get()
|
||||
(c, r, skip) = qret.get()
|
||||
compile_error_files += c
|
||||
run_error_files += r
|
||||
skip_files += s
|
||||
skip_files += skip
|
||||
|
||||
if options.non_interactive:
|
||||
sys.stdout.write(" Done %d / %d\n" % (finished_tests_counter.value, total_tests))
|
||||
print_debug(" Done %d / %d\n" % (finished_tests_counter.value, total_tests), s, run_tests_log)
|
||||
if len(skip_files) > 0:
|
||||
skip_files.sort()
|
||||
sys.stdout.write("%d / %d tests SKIPPED:\n" % (len(skip_files), total_tests))
|
||||
print_debug("%d / %d tests SKIPPED:\n" % (len(skip_files), total_tests), s, run_tests_log)
|
||||
for f in skip_files:
|
||||
sys.stdout.write("\t%s\n" % f)
|
||||
print_debug("\t%s\n" % f, s, run_tests_log)
|
||||
if len(compile_error_files) > 0:
|
||||
compile_error_files.sort()
|
||||
sys.stdout.write("%d / %d tests FAILED compilation:\n" % (len(compile_error_files), total_tests))
|
||||
print_debug("%d / %d tests FAILED compilation:\n" % (len(compile_error_files), total_tests), s, run_tests_log)
|
||||
for f in compile_error_files:
|
||||
sys.stdout.write("\t%s\n" % f)
|
||||
print_debug("\t%s\n" % f, s, run_tests_log)
|
||||
if len(run_error_files) > 0:
|
||||
run_error_files.sort()
|
||||
sys.stdout.write("%d / %d tests FAILED execution:\n" % (len(run_error_files), total_tests))
|
||||
print_debug("%d / %d tests FAILED execution:\n" % (len(run_error_files), total_tests), s, run_tests_log)
|
||||
for f in run_error_files:
|
||||
sys.stdout.write("\t%s\n" % f)
|
||||
print_debug("\t%s\n" % f, s, run_tests_log)
|
||||
|
||||
R = file_check(compile_error_files, run_error_files)
|
||||
|
||||
if options.time:
|
||||
sys.stdout.write("Elapsed time: %d s\n" % elapsed_time)
|
||||
print_debug("Elapsed time: %d s\n" % elapsed_time, s, run_tests_log)
|
||||
|
||||
sys.exit(len(compile_error_files) + len(run_error_files))
|
||||
return R
|
||||
|
||||
|
||||
from optparse import OptionParser
|
||||
import multiprocessing
|
||||
from ctypes import c_int
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import re
|
||||
import signal
|
||||
import random
|
||||
import string
|
||||
import subprocess
|
||||
import shlex
|
||||
import platform
|
||||
import tempfile
|
||||
import os.path
|
||||
import time
|
||||
# our functions
|
||||
import common
|
||||
print_debug = common.print_debug
|
||||
error = common.error
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser()
|
||||
parser.add_option("-r", "--random-shuffle", dest="random", help="Randomly order tests",
|
||||
default=False, action="store_true")
|
||||
parser.add_option("-g", "--generics-include", dest="include_file", help="Filename for header implementing functions for generics",
|
||||
default=None)
|
||||
parser.add_option("-f", "--ispc-flags", dest="ispc_flags", help="Additional flags for ispc (-g, -O1, ...)",
|
||||
default="")
|
||||
parser.add_option('-t', '--target', dest='target',
|
||||
help='Set compilation target (sse2-i32x4, sse2-i32x8, sse4-i32x4, sse4-i32x8, sse4-i16x8, sse4-i8x16, avx1-i32x8, avx1-i32x16, avx1.1-i32x8, avx1.1-i32x16, avx2-i32x8, avx2-i32x16, generic-x1, generic-x4, generic-x8, generic-x16, generic-x32, generic-x64)',
|
||||
default="sse4")
|
||||
parser.add_option('-a', '--arch', dest='arch',
|
||||
help='Set architecture (arm, x86, x86-64)',
|
||||
default="x86-64")
|
||||
parser.add_option("-c", "--compiler", dest="compiler_exe", help="C/C++ compiler binary to use to run tests",
|
||||
default=None)
|
||||
parser.add_option('-o', '--no-opt', dest='no_opt', help='Disable optimization',
|
||||
default=False, action="store_true")
|
||||
parser.add_option('-j', '--jobs', dest='num_jobs', help='Maximum number of jobs to run in parallel',
|
||||
default="1024", type="int")
|
||||
parser.add_option('-v', '--verbose', dest='verbose', help='Enable verbose output',
|
||||
default=False, action="store_true")
|
||||
parser.add_option('--wrap-exe', dest='wrapexe',
|
||||
help='Executable to wrap test runs with (e.g. "valgrind")',
|
||||
default="")
|
||||
parser.add_option('--time', dest='time', help='Enable time output',
|
||||
default=False, action="store_true")
|
||||
parser.add_option('--non-interactive', dest='non_interactive', help='Disable interactive status updates',
|
||||
default=False, action="store_true")
|
||||
parser.add_option('-u', "--update", dest='update', help='Update file with fails (F of FP)', default="")
|
||||
parser.add_option('-s', "--silent", dest='silent', help='enable silent mode without any output', default=False,
|
||||
action = "store_true")
|
||||
parser.add_option("--file", dest='in_file', help='file to save run_tests output', default="")
|
||||
parser.add_option("--verify", dest='verify', help='verify the file fail_db.txt', default=False, action="store_true")
|
||||
(options, args) = parser.parse_args()
|
||||
L = run_tests(options, args, 1)
|
||||
exit(0)
|
||||
|
||||
Reference in New Issue
Block a user