runtests.py 8.24 KB
Newer Older
1 2 3 4 5 6 7 8
# 
# (c) Simon Marlow 2002
#

import sys
import os
import string
import getopt
9
import platform
10
import time
11
import re
12

13 14
from testutil import *
from testglobals import *
15

16 17 18 19 20
# Readline sometimes spews out ANSI escapes for some values of TERM,
# which result in test failures. Thus set TERM to a nice, simple, safe
# value.
os.environ['TERM'] = 'vt100'

21 22 23 24 25
if sys.platform == "cygwin":
    cygwin = True
else:
    cygwin = False

26
global config
27
config = getConfig() # get it from testglobals
28 29 30 31 32 33 34 35 36

# -----------------------------------------------------------------------------
# cmd-line options

long_options = [
  "config=",  		# config file
  "rootdir=", 		# root of tree containing tests (default: .)
  "output-summary=", 	# file in which to save the (human-readable) summary
  "only=",		# just this test (can be give multiple --only= flags)
37
  "way=",		# just this way
38
  "skipway=",		# skip this way
ei@vuokko.info's avatar
ei@vuokko.info committed
39
  "threads=",           # threads to run simultaneously
40
  "check-files-written", # check files aren't written by multiple tests
41 42 43 44 45 46 47 48 49 50 51 52 53 54
  ]

opts, args = getopt.getopt(sys.argv[1:], "e:", long_options)
       
for opt,arg in opts:
    if opt == '--config':
        execfile(arg)

    # -e is a string to execute from the command line.  For example:
    # testframe -e 'config.compiler=ghc-5.04'
    if opt == '-e':
        exec arg

    if opt == '--rootdir':
55
        config.rootdirs.append(arg)
56 57 58 59 60 61 62

    if opt == '--output-summary':
        config.output_summary = arg

    if opt == '--only':
        config.only.append(arg)

63
    if opt == '--way':
krc's avatar
krc committed
64
        if (arg not in config.run_ways and arg not in config.compile_ways and arg not in config.other_ways):
65 66 67
            sys.stderr.write("ERROR: requested way \'" +
                             arg + "\' does not exist\n")
            sys.exit(1)
68 69 70 71
        config.cmdline_ways = [arg] + config.cmdline_ways
        if (arg in config.other_ways):
            config.run_ways = [arg] + config.run_ways
            config.compile_ways = [arg] + config.compile_ways
ei@vuokko.info's avatar
ei@vuokko.info committed
72

73 74 75 76 77 78 79 80 81
    if opt == '--skipway':
        if (arg not in config.run_ways and arg not in config.compile_ways and arg not in config.other_ways):
            sys.stderr.write("ERROR: requested way \'" +
                             arg + "\' does not exist\n")
            sys.exit(1)
        config.other_ways = filter(neq(arg), config.other_ways)
        config.run_ways = filter(neq(arg), config.run_ways)
        config.compile_ways = filter(neq(arg), config.compile_ways)

ei@vuokko.info's avatar
ei@vuokko.info committed
82
    if opt == '--threads':
Ian Lynagh's avatar
Ian Lynagh committed
83 84 85
        config.threads = int(arg)
        config.use_threads = 1

86 87 88
    if opt == '--check-files-written':
        config.check_files_written = True

Ian Lynagh's avatar
Ian Lynagh committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
if config.use_threads == 1:
    # Trac #1558 says threads don't work in python 2.4.4, but do
    # in 2.5.2. Probably >= 2.5 is sufficient, but let's be
    # conservative here.
    # Some versions of python have things like '1c1' for some of
    # these components (see trac #3091), but int() chokes on the
    # 'c1', so we drop it.
    (maj, min, pat) = platform.python_version_tuple()
    # We wrap maj, min, and pat in str() to work around a bug in python
    # 2.6.1
    maj = int(re.sub('[^0-9].*', '', str(maj)))
    min = int(re.sub('[^0-9].*', '', str(min)))
    pat = int(re.sub('[^0-9].*', '', str(pat)))
    if (maj, min, pat) < (2, 5, 2):
        print "Warning: Ignoring request to use threads as python version < 2.5.2"
        config.use_threads = 0
    if windows:
        print "Warning: Ignoring request to use threads as running on Windows"
        config.use_threads = 0
108

Ian Lynagh's avatar
Ian Lynagh committed
109 110 111 112 113 114 115 116
config.cygwin = False
config.msys = False
if windows:
    if cygwin:
        config.cygwin = True
    else:
        config.msys = True

117 118
# Try to use UTF8
if windows:
119
    import ctypes
120
    if cygwin:
Ian Lynagh's avatar
Ian Lynagh committed
121 122 123 124 125 126 127
        # Is this actually right? Which calling convention does it use?
        # As of the time of writing, ctypes.windll doesn't exist in the
        # cygwin python, anyway.
        mydll = ctypes.cdll
    else:
        mydll = ctypes.windll

128 129 130
    # This actually leaves the terminal in codepage 65001 (UTF8) even
    # after python terminates. We ought really remember the old codepage
    # and set it back.
Ian Lynagh's avatar
Ian Lynagh committed
131
    if mydll.kernel32.SetConsoleCP(65001) == 0:
132
        raise Exception("Failure calling SetConsoleCP(65001)")
Ian Lynagh's avatar
Ian Lynagh committed
133
    if mydll.kernel32.SetConsoleOutputCP(65001) == 0:
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
        raise Exception("Failure calling SetConsoleOutputCP(65001)")
else:
    # Try and find a utf8 locale to use
    # First see if we already have a UTF8 locale
    h = os.popen('locale | grep LC_CTYPE | grep -i utf', 'r')
    v = h.read()
    h.close()
    if v == '':
        # We don't, so now see if 'locale -a' works
        h = os.popen('locale -a', 'r')
        v = h.read()
        h.close()
        if v != '':
            # If it does then use the first utf8 locale that is available
            h = os.popen('locale -a | grep -i "utf8\|utf-8" 2>/dev/null', 'r')
            v = h.readline().strip()
            h.close()
            if v != '':
                os.environ['LC_ALL'] = v
                print "setting LC_ALL to", v
            else:
                print 'WARNING: No UTF8 locale found.'
                print 'You may get some spurious test failures.'

158 159 160
# This has to come after arg parsing as the args can change the compiler
get_compiler_info()

161 162 163 164
# Can't import this earlier as we need to know if threading will be
# enabled or not
from testlib import *

165 166
# On Windows we need to set $PATH to include the paths to all the DLLs
# in order for the dynamic library tests to work.
Ian Lynagh's avatar
Ian Lynagh committed
167
if windows or darwin:
168
    pkginfo = getStdout([config.ghc_pkg, 'dump'])
169
    topdir = config.libdir
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
    for line in pkginfo.split('\n'):
        if line.startswith('library-dirs:'):
            path = line.rstrip()
            path = re.sub('^library-dirs: ', '', path)
            path = re.sub('\\$topdir', topdir, path)
            if path.startswith('"'):
                path = re.sub('^"(.*)"$', '\\1', path)
                path = re.sub('\\\\(.)', '\\1', path)
            if windows:
                if cygwin:
                    # On cygwin we can't put "c:\foo" in $PATH, as : is a
                    # field separator. So convert to /cygdrive/c/foo instead.
                    # Other pythons use ; as the separator, so no problem.
                    path = re.sub('([a-zA-Z]):', '/cygdrive/\\1', path)
                    path = re.sub('\\\\', '/', path)
                os.environ['PATH'] = os.pathsep.join([path, os.environ.get("PATH", "")])
            else:
                # darwin
                os.environ['DYLD_LIBRARY_PATH'] = os.pathsep.join([path, os.environ.get("DYLD_LIBRARY_PATH", "")])
189

190 191 192 193 194 195 196 197 198
global testopts_local
testopts_local.x = TestOptions()

global thisdir_testopts
thisdir_testopts = getThisDirTestOpts()

if config.use_threads:
    t.lock = threading.Lock()
    t.thread_pool = threading.Condition(t.lock)
199
    t.lockFilesWritten = threading.Lock()
200 201
    t.running_threads = 0

202 203 204 205 206 207
# if timeout == -1 then we try to calculate a sensible value
if config.timeout == -1:
    config.timeout = int(read_no_crs(config.top + '/timeout/calibrate.out'))

print 'Timeout is ' + str(config.timeout)

208 209 210
# -----------------------------------------------------------------------------
# The main dude

211 212 213 214
if config.rootdirs == []:
    config.rootdirs = ['.']

t_files = findTFiles(config.rootdirs)
215 216 217 218 219

print 'Found', len(t_files), '.T files...'

t = getTestRun()

220 221 222 223 224 225
# Avoid cmd.exe built-in 'date' command on Windows
if not windows:
    t.start_time = chop(os.popen('date').read())
else:
    t.start_time = 'now'

226 227 228 229 230 231
print 'Beginning test run at', t.start_time

# set stdout to unbuffered (is this the best way to do it?)
sys.stdout.flush()
sys.stdout = os.fdopen(sys.__stdout__.fileno(), "w", 0)

232
# First collect all the tests to be run
233
for file in t_files:
234
    print '====> Scanning', file
235 236 237 238
    newTestDir(os.path.dirname(file))
    try:
        execfile(file)
    except:
239
        print '*** framework failure: found an error while executing ', file, ':'
240
        t.n_framework_failures = t.n_framework_failures + 1
241
        traceback.print_exc()
242 243 244 245 246 247 248 249 250 251 252

# Now run all the tests
if config.use_threads:
    t.running_threads=0
for oneTest in allTests:
    oneTest()
if config.use_threads:
    t.thread_pool.acquire()
    while t.running_threads>0:
        t.thread_pool.wait()
    t.thread_pool.release()
ei@vuokko.info's avatar
ei@vuokko.info committed
253
        
254 255 256 257 258 259 260
summary(t, sys.stdout)

if config.output_summary != '':
    summary(t, open(config.output_summary, 'w'))

sys.exit(0)