ghc-dup: bc93355477debfa6afb57e33e6afd603a605a2ea
1: #
2: # (c) Simon Marlow 2002
3: #
4:
5: import sys
6: import os
7: import string
8: import getopt
9: import platform
10: import time
11: import re
12:
13: # We don't actually need subprocess in runtests.py, but:
14: # * We do need it in testlibs.py
15: # * We can't import testlibs.py until after we have imported ctypes
16: # * If we import ctypes before subprocess on cygwin, then sys.exit(0)
17: # says "Aborted" and we fail with exit code 134.
18: # So we import it here first, so that the testsuite doesn't appear to fail.
19: try:
20: import subprocess
21: except:
22: pass
23:
24: from testutil import *
25: from testglobals import *
26:
27: # Readline sometimes spews out ANSI escapes for some values of TERM,
28: # which result in test failures. Thus set TERM to a nice, simple, safe
29: # value.
30: os.environ['TERM'] = 'vt100'
31:
32: global config
33: config = getConfig() # get it from testglobals
34:
35: # -----------------------------------------------------------------------------
36: # cmd-line options
37:
38: long_options = [
39: "config=", # config file
40: "rootdir=", # root of tree containing tests (default: .)
41: "output-summary=", # file in which to save the (human-readable) summary
42: "only=", # just this test (can be give multiple --only= flags)
43: "way=", # just this way
44: "skipway=", # skip this way
45: "threads=", # threads to run simultaneously
46: "check-files-written", # check files aren't written by multiple tests
47: ]
48:
49: opts, args = getopt.getopt(sys.argv[1:], "e:", long_options)
50:
51: for opt,arg in opts:
52: if opt == '--config':
53: execfile(arg)
54:
55: # -e is a string to execute from the command line. For example:
56: # testframe -e 'config.compiler=ghc-5.04'
57: if opt == '-e':
58: exec arg
59:
60: if opt == '--rootdir':
61: config.rootdirs.append(arg)
62:
63: if opt == '--output-summary':
64: config.output_summary = arg
65:
66: if opt == '--only':
67: config.only.append(arg)
68:
69: if opt == '--way':
70: if (arg not in config.run_ways and arg not in config.compile_ways and arg not in config.other_ways):
71: sys.stderr.write("ERROR: requested way \'" +
72: arg + "\' does not exist\n")
73: sys.exit(1)
74: config.cmdline_ways = [arg] + config.cmdline_ways
75: if (arg in config.other_ways):
76: config.run_ways = [arg] + config.run_ways
77: config.compile_ways = [arg] + config.compile_ways
78:
79: if opt == '--skipway':
80: if (arg not in config.run_ways and arg not in config.compile_ways and arg not in config.other_ways):
81: sys.stderr.write("ERROR: requested way \'" +
82: arg + "\' does not exist\n")
83: sys.exit(1)
84: config.other_ways = filter(neq(arg), config.other_ways)
85: config.run_ways = filter(neq(arg), config.run_ways)
86: config.compile_ways = filter(neq(arg), config.compile_ways)
87:
88: if opt == '--threads':
89: config.threads = int(arg)
90: config.use_threads = 1
91:
92: if opt == '--check-files-written':
93: config.check_files_written = True
94:
95: if config.use_threads == 1:
96: # Trac #1558 says threads don't work in python 2.4.4, but do
97: # in 2.5.2. Probably >= 2.5 is sufficient, but let's be
98: # conservative here.
99: # Some versions of python have things like '1c1' for some of
100: # these components (see trac #3091), but int() chokes on the
101: # 'c1', so we drop it.
102: (maj, min, pat) = platform.python_version_tuple()
103: # We wrap maj, min, and pat in str() to work around a bug in python
104: # 2.6.1
105: maj = int(re.sub('[^0-9].*', '', str(maj)))
106: min = int(re.sub('[^0-9].*', '', str(min)))
107: pat = int(re.sub('[^0-9].*', '', str(pat)))
108: if (maj, min, pat) < (2, 5, 2):
109: print "Warning: Ignoring request to use threads as python version < 2.5.2"
110: config.use_threads = 0
111: # We also need to disable threads for python 2.7.2, because of
112: # this bug: http://bugs.python.org/issue13817
113: elif (maj, min, pat) == (2, 7, 2):
114: print "Warning: Ignoring request to use threads as python version is 2.7.2"
115: print "See http://bugs.python.org/issue13817 for details."
116: config.use_threads = 0
117: if windows:
118: print "Warning: Ignoring request to use threads as running on Windows"
119: config.use_threads = 0
120:
121: config.cygwin = False
122: config.msys = False
123: if windows:
124: h = os.popen('uname -s', 'r')
125: v = h.read()
126: h.close()
127: if v.startswith("CYGWIN"):
128: config.cygwin = True
129: elif v.startswith("MINGW32"):
130: config.msys = True
131: else:
132: raise Exception("Can't detect Windows terminal type")
133:
134: # Try to use UTF8
135: if windows:
136: import ctypes
137: if config.cygwin:
138: # Is this actually right? Which calling convention does it use?
139: # As of the time of writing, ctypes.windll doesn't exist in the
140: # cygwin python, anyway.
141: mydll = ctypes.cdll
142: else:
143: mydll = ctypes.windll
144:
145: # This actually leaves the terminal in codepage 65001 (UTF8) even
146: # after python terminates. We ought really remember the old codepage
147: # and set it back.
148: if mydll.kernel32.SetConsoleCP(65001) == 0:
149: raise Exception("Failure calling SetConsoleCP(65001)")
150: if mydll.kernel32.SetConsoleOutputCP(65001) == 0:
151: raise Exception("Failure calling SetConsoleOutputCP(65001)")
152: else:
153: # Try and find a utf8 locale to use
154: # First see if we already have a UTF8 locale
155: h = os.popen('locale | grep LC_CTYPE | grep -i utf', 'r')
156: v = h.read()
157: h.close()
158: if v == '':
159: # We don't, so now see if 'locale -a' works
160: h = os.popen('locale -a', 'r')
161: v = h.read()
162: h.close()
163: if v != '':
164: # If it does then use the first utf8 locale that is available
165: h = os.popen('locale -a | grep -i "utf8\|utf-8" 2>/dev/null', 'r')
166: v = h.readline().strip()
167: h.close()
168: if v != '':
169: os.environ['LC_ALL'] = v
170: print "setting LC_ALL to", v
171: else:
172: print 'WARNING: No UTF8 locale found.'
173: print 'You may get some spurious test failures.'
174:
175: # This has to come after arg parsing as the args can change the compiler
176: get_compiler_info()
177:
178: # Can't import this earlier as we need to know if threading will be
179: # enabled or not
180: from testlib import *
181:
182: # On Windows we need to set $PATH to include the paths to all the DLLs
183: # in order for the dynamic library tests to work.
184: if windows or darwin:
185: pkginfo = getStdout([config.ghc_pkg, 'dump'])
186: topdir = config.libdir
187: for line in pkginfo.split('\n'):
188: if line.startswith('library-dirs:'):
189: path = line.rstrip()
190: path = re.sub('^library-dirs: ', '', path)
191: path = re.sub('\\$topdir', topdir, path)
192: if path.startswith('"'):
193: path = re.sub('^"(.*)"$', '\\1', path)
194: path = re.sub('\\\\(.)', '\\1', path)
195: if windows:
196: if config.cygwin:
197: # On cygwin we can't put "c:\foo" in $PATH, as : is a
198: # field separator. So convert to /cygdrive/c/foo instead.
199: # Other pythons use ; as the separator, so no problem.
200: path = re.sub('([a-zA-Z]):', '/cygdrive/\\1', path)
201: path = re.sub('\\\\', '/', path)
202: os.environ['PATH'] = os.pathsep.join([path, os.environ.get("PATH", "")])
203: else:
204: # darwin
205: os.environ['DYLD_LIBRARY_PATH'] = os.pathsep.join([path, os.environ.get("DYLD_LIBRARY_PATH", "")])
206:
207: global testopts_local
208: testopts_local.x = TestOptions()
209:
210: global thisdir_testopts
211: thisdir_testopts = getThisDirTestOpts()
212:
213: if config.use_threads:
214: t.lock = threading.Lock()
215: t.thread_pool = threading.Condition(t.lock)
216: t.lockFilesWritten = threading.Lock()
217: t.running_threads = 0
218:
219: # if timeout == -1 then we try to calculate a sensible value
220: if config.timeout == -1:
221: config.timeout = int(read_no_crs(config.top + '/timeout/calibrate.out'))
222:
223: print 'Timeout is ' + str(config.timeout)
224:
225: # -----------------------------------------------------------------------------
226: # The main dude
227:
228: if config.rootdirs == []:
229: config.rootdirs = ['.']
230:
231: t_files = findTFiles(config.rootdirs)
232:
233: print 'Found', len(t_files), '.T files...'
234:
235: t = getTestRun()
236:
237: # Avoid cmd.exe built-in 'date' command on Windows
238: if not windows:
239: t.start_time = chop(os.popen('date').read())
240: else:
241: t.start_time = 'now'
242:
243: print 'Beginning test run at', t.start_time
244:
245: # set stdout to unbuffered (is this the best way to do it?)
246: sys.stdout.flush()
247: sys.stdout = os.fdopen(sys.__stdout__.fileno(), "w", 0)
248:
249: # First collect all the tests to be run
250: for file in t_files:
251: print '====> Scanning', file
252: newTestDir(os.path.dirname(file))
253: try:
254: execfile(file)
255: except:
256: print '*** framework failure: found an error while executing ', file, ':'
257: t.n_framework_failures = t.n_framework_failures + 1
258: traceback.print_exc()
259:
260: # Now run all the tests
261: if config.use_threads:
262: t.running_threads=0
263: for oneTest in allTests:
264: oneTest()
265: if config.use_threads:
266: t.thread_pool.acquire()
267: while t.running_threads>0:
268: t.thread_pool.wait()
269: t.thread_pool.release()
270:
271: summary(t, sys.stdout)
272:
273: if config.output_summary != '':
274: summary(t, open(config.output_summary, 'w'))
275:
276: sys.exit(0)
277:
Generated by git2html.