Updates and slight refactor in fix
[scons.git] / bin / scons-test.py
blob868688c1ba51994623fb332484816f7299bae5c7
1 #!/usr/bin/env python
3 # MIT License
5 # Copyright The SCons Foundation
7 # Permission is hereby granted, free of charge, to any person obtaining
8 # a copy of this software and associated documentation files (the
9 # "Software"), to deal in the Software without restriction, including
10 # without limitation the rights to use, copy, modify, merge, publish,
11 # distribute, sublicense, and/or sell copies of the Software, and to
12 # permit persons to whom the Software is furnished to do so, subject to
13 # the following conditions:
15 # The above copyright notice and this permission notice shall be included
16 # in all copies or substantial portions of the Software.
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
19 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
20 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 """
28 scons-test.py - test a particular SCons version.
30 Takes an scons-src-{version}.zip file, unwraps it in a temporary location,
31 and calls runtest.py to execute one or more of its tests.
33 The default is to download the latest scons-src archive from the SCons
34 web site, and to execute all of the tests.
36 With a little more work, this will become the basis of an automated
37 testing and reporting system that anyone will be able to use to
38 participate in testing SCons on their system and regularly reporting
39 back the results. A --xml option is a stab at gathering a lot of
40 relevant information about the system, the Python version, etc.,
41 so that problems on different platforms can be identified sooner.
42 """
44 import atexit
45 import getopt
46 import os
47 import os.path
48 import sys
49 import tempfile
50 import time
51 import zipfile
52 from urllib.request import urlretrieve
54 helpstr = """\
55 Usage: scons-test.py [-f zipfile] [-o outdir] [-v] [--xml] [runtest arguments]
56 Options:
57 -f FILE Specify input .zip FILE name
58 -o DIR, --out DIR Change output directory name to DIR
59 -v, --verbose Print file names when extracting
60 --xml XML output
61 """
63 opts, args = getopt.getopt(sys.argv[1:],
64 "f:o:v",
65 ['file=', 'out=', 'verbose', 'xml'])
67 format = None
68 outdir = None
69 printname = lambda x: x
70 inputfile = 'http://scons.sourceforge.net/scons-src-latest.zip'
72 for o, a in opts:
73 if o == '-f' or o == '--file':
74 inputfile = a
75 elif o == '-o' or o == '--out':
76 outdir = a
77 elif o == '-v' or o == '--verbose':
78 def printname(x):
79 print(x)
80 elif o == '--xml':
81 format = o
83 startdir = os.getcwd()
85 tempfile.template = 'scons-test.'
86 tempdir = tempfile.mktemp()
88 if not os.path.exists(tempdir):
89 os.mkdir(tempdir)
90 def cleanup(tempdir=tempdir):
91 import shutil
92 os.chdir(startdir)
93 shutil.rmtree(tempdir)
94 atexit.register(cleanup)
96 # Fetch the input file if it happens to be across a network somewhere.
97 # Ohmigod, does Python make this simple...
98 inputfile, headers = urlretrieve(inputfile)
100 # Unzip the header file in the output directory. We use our own code
101 # (lifted from scons-unzip.py) to make the output subdirectory name
102 # match the basename of the .zip file.
103 zf = zipfile.ZipFile(inputfile, 'r')
105 if outdir is None:
106 name, _ = os.path.splitext(os.path.basename(inputfile))
107 outdir = os.path.join(tempdir, name)
109 def outname(n, outdir=outdir):
110 l = []
111 while True:
112 n, tail = os.path.split(n)
113 if not n:
114 break
115 l.append(tail)
116 l.append(outdir)
117 l.reverse()
118 return os.path.join(*l)
120 for name in zf.namelist():
121 dest = outname(name)
122 dir = os.path.dirname(dest)
123 try:
124 os.makedirs(dir)
125 except:
126 pass
127 printname(dest)
128 # if the file exists, then delete it before writing
129 # to it so that we don't end up trying to write to a symlink:
130 if os.path.isfile(dest) or os.path.islink(dest):
131 os.unlink(dest)
132 if not os.path.isdir(dest):
133 open(dest, 'w').write(zf.read(name))
135 os.chdir(outdir)
137 # Load (by hand) the SCons modules we just unwrapped so we can
138 # extract their version information. Note that we have to override
139 # SCons.Script.main() with a do_nothing() function, because loading up
140 # the 'scons' script will actually try to execute SCons...
141 src_script = os.path.join(outdir, 'src', 'script')
142 src_engine = os.path.join(outdir, 'src', 'engine')
143 src_engine_SCons = os.path.join(src_engine, 'SCons')
145 fp, pname, desc = imp.find_module('SCons', [src_engine])
146 SCons = imp.load_module('SCons', fp, pname, desc)
148 fp, pname, desc = imp.find_module('Script', [src_engine_SCons])
149 SCons.Script = imp.load_module('Script', fp, pname, desc)
151 def do_nothing():
152 pass
153 SCons.Script.main = do_nothing
155 fp, pname, desc = imp.find_module('scons', [src_script])
156 scons = imp.load_module('scons', fp, pname, desc)
157 fp.close()
159 # Default is to run all the tests by passing the -a flags to runtest.py.
160 if not args:
161 runtest_args = '-a'
162 else:
163 runtest_args = ' '.join(args)
165 if format == '--xml':
167 print("<scons_test_run>")
168 print(" <sys>")
169 sys_keys = ['byteorder', 'exec_prefix', 'executable', 'maxint', 'maxunicode', 'platform', 'prefix', 'version', 'version_info']
170 for k in sys_keys:
171 print(" <%s>%s</%s>" % (k, sys.__dict__[k], k))
172 print(" </sys>")
174 fmt = '%a %b %d %H:%M:%S %Y'
175 print(" <time>")
176 print(" <gmtime>%s</gmtime>" % time.strftime(fmt, time.gmtime()))
177 print(" <localtime>%s</localtime>" % time.strftime(fmt, time.localtime()))
178 print(" </time>")
180 print(" <tempdir>%s</tempdir>" % tempdir)
182 def print_version_info(tag, module):
183 print(" <%s>" % tag)
184 print(" <version>%s</version>" % module.__version__)
185 print(" <build>%s</build>" % module.__build__)
186 print(" <buildsys>%s</buildsys>" % module.__buildsys__)
187 print(" <date>%s</date>" % module.__date__)
188 print(" <developer>%s</developer>" % module.__developer__)
189 print(" </%s>" % tag)
191 print(" <scons>")
192 print_version_info("script", scons)
193 print_version_info("engine", SCons)
194 print(" </scons>")
196 environ_keys = [
197 'PATH',
198 'SCONSFLAGS',
199 'SCONS_LIB_DIR',
200 'PYTHON_ROOT',
201 'QTDIR',
203 'COMSPEC',
204 'INTEL_LICENSE_FILE',
205 'INCLUDE',
206 'LIB',
207 'MSDEVDIR',
208 'OS',
209 'PATHEXT',
210 'SystemRoot',
211 'TEMP',
212 'TMP',
213 'USERNAME',
214 'VXDOMNTOOLS',
215 'WINDIR',
216 'XYZZY'
218 'ENV',
219 'HOME',
220 'LANG',
221 'LANGUAGE',
222 'LOGNAME',
223 'MACHINE',
224 'OLDPWD',
225 'PWD',
226 'OPSYS',
227 'SHELL',
228 'TMPDIR',
229 'USER',
232 print(" <environment>")
233 for key in sorted(environ_keys):
234 value = os.environ.get(key)
235 if value:
236 print(" <variable>")
237 print(" <name>%s</name>" % key)
238 print(" <value>%s</value>" % value)
239 print(" </variable>")
240 print(" </environment>")
242 command = '"%s" runtest.py -q -o - --xml %s' % (sys.executable, runtest_args)
243 #print(command)
244 os.system(command)
245 print("</scons_test_run>")
247 else:
249 def print_version_info(tag, module):
250 print("\t%s: v%s.%s, %s, by %s on %s" % (tag,
251 module.__version__,
252 module.__build__,
253 module.__date__,
254 module.__developer__,
255 module.__buildsys__))
257 print("SCons by Steven Knight et al.:")
258 print_version_info("script", scons)
259 print_version_info("engine", SCons)
261 command = '"%s" runtest.py %s' % (sys.executable, runtest_args)
262 #print(command)
263 os.system(command)
265 # Local Variables:
266 # tab-width:4
267 # indent-tabs-mode:nil
268 # End:
269 # vim: set expandtab tabstop=4 shiftwidth=4: