8d1950f181bb2997d82938e9f01a5fd6266d8b23
[scons.git] / bin / scons-test.py
1 #!/usr/bin/env python
2 #
3 # A script that takes an scons-src-{version}.zip file, unwraps it in
4 # a temporary location, and calls runtest.py to execute one or more of
5 # its tests.
6 #
7 # The default is to download the latest scons-src archive from the SCons
8 # web site, and to execute all of the tests.
9 #
10 # With a little more work, this will become the basis of an automated
11 # testing and reporting system that anyone will be able to use to
12 # participate in testing SCons on their system and regularly reporting
13 # back the results.  A --xml option is a stab at gathering a lot of
14 # relevant information about the system, the Python version, etc.,
15 # so that problems on different platforms can be identified sooner.
16 #
17
18 import getopt
19 import imp
20 import os
21 import os.path
22 import sys
23 import tempfile
24 import time
25 import urllib
26 import zipfile
27
28 helpstr = """\
29 Usage: scons-test.py [-f zipfile] [-o outdir] [-v] [--xml] [runtest arguments]
30 Options:
31   -f FILE                     Specify input .zip FILE name
32   -o DIR, --out DIR           Change output directory name to DIR
33   -v, --verbose               Print file names when extracting
34   --xml                       XML output
35 """
36
37 opts, args = getopt.getopt(sys.argv[1:],
38                            "f:o:v",
39                            ['file=', 'out=', 'verbose', 'xml'])
40
41 format = None
42 outdir = None
43 printname = lambda x: x
44 inputfile = 'http://scons.sourceforge.net/scons-src-latest.zip'
45
46 for o, a in opts:
47     if o == '-f' or o == '--file':
48         inputfile = a
49     elif o == '-o' or o == '--out':
50         outdir = a
51     elif o == '-v' or o == '--verbose':
52         def printname(x):
53             print x
54     elif o == '--xml':
55         format = o
56
57 startdir = os.getcwd()
58
59 tempfile.template = 'scons-test.'
60 tempdir = tempfile.mktemp()
61
62 if not os.path.exists(tempdir):
63     os.mkdir(tempdir)
64     def cleanup(tempdir=tempdir):
65         import shutil
66         os.chdir(startdir)
67         shutil.rmtree(tempdir)
68     sys.exitfunc = cleanup
69
70 # Fetch the input file if it happens to be across a network somewhere.
71 # Ohmigod, does Python make this simple...
72 inputfile, headers = urllib.urlretrieve(inputfile)
73
74 # Unzip the header file in the output directory.  We use our own code
75 # (lifted from scons-unzip.py) to make the output subdirectory name
76 # match the basename of the .zip file.
77 zf = zipfile.ZipFile(inputfile, 'r')
78
79 if outdir is None:
80     name, _ = os.path.splitext(os.path.basename(inputfile))
81     outdir = os.path.join(tempdir, name)
82
83 def outname(n, outdir=outdir):
84     l = []
85     while 1:
86         n, tail = os.path.split(n)
87         if not n:
88             break
89         l.append(tail)
90     l.append(outdir)
91     l.reverse()
92     return os.path.join(*l)
93
94 for name in zf.namelist():
95     dest = outname(name)
96     dir = os.path.dirname(dest)
97     try:
98         os.makedirs(dir)
99     except:
100         pass
101     printname(dest)
102     # if the file exists, then delete it before writing
103     # to it so that we don't end up trying to write to a symlink:
104     if os.path.isfile(dest) or os.path.islink(dest):
105         os.unlink(dest)
106     if not os.path.isdir(dest):
107         open(dest, 'w').write(zf.read(name))
108
109 os.chdir(outdir)
110
111 # Load (by hand) the SCons modules we just unwrapped so we can
112 # extract their version information.  Note that we have to override
113 # SCons.Script.main() with a do_nothing() function, because loading up
114 # the 'scons' script will actually try to execute SCons...
115 src_script = os.path.join(outdir, 'src', 'script')
116 src_engine = os.path.join(outdir, 'src', 'engine')
117 src_engine_SCons = os.path.join(src_engine, 'SCons')
118
119 fp, pname, desc = imp.find_module('SCons', [src_engine])
120 SCons = imp.load_module('SCons', fp, pname, desc)
121
122 fp, pname, desc = imp.find_module('Script', [src_engine_SCons])
123 SCons.Script = imp.load_module('Script', fp, pname, desc)
124
125 def do_nothing():
126     pass
127 SCons.Script.main = do_nothing
128
129 fp, pname, desc = imp.find_module('scons', [src_script])
130 scons = imp.load_module('scons', fp, pname, desc)
131 fp.close()
132
133 # Default is to run all the tests by passing the -a flags to runtest.py.
134 if not args:
135     runtest_args = '-a'
136 else:
137     runtest_args = ' '.join(args)
138
139 if format == '--xml':
140
141     print "<scons_test_run>"
142     print "  <sys>"
143     sys_keys = ['byteorder', 'exec_prefix', 'executable', 'maxint', 'maxunicode', 'platform', 'prefix', 'version', 'version_info']
144     for k in sys_keys:
145         print "    <%s>%s</%s>" % (k, sys.__dict__[k], k)
146     print "  </sys>"
147
148     fmt = '%a %b %d %H:%M:%S %Y'
149     print "  <time>"
150     print "    <gmtime>%s</gmtime>" % time.strftime(fmt, time.gmtime())
151     print "    <localtime>%s</localtime>" % time.strftime(fmt, time.localtime())
152     print "  </time>"
153
154     print "  <tempdir>%s</tempdir>" % tempdir
155
156     def print_version_info(tag, module):
157         print "    <%s>" % tag
158         print "      <version>%s</version>" % module.__version__
159         print "      <build>%s</build>" % module.__build__
160         print "      <buildsys>%s</buildsys>" % module.__buildsys__
161         print "      <date>%s</date>" % module.__date__
162         print "      <developer>%s</developer>" % module.__developer__
163         print "    </%s>" % tag
164
165     print "  <scons>"
166     print_version_info("script", scons)
167     print_version_info("engine", SCons)
168     print "  </scons>"
169
170     environ_keys = [
171         'PATH',
172         'SCONSFLAGS',
173         'SCONS_LIB_DIR',
174         'PYTHON_ROOT',
175         'QTDIR',
176
177         'COMSPEC',
178         'INTEL_LICENSE_FILE',
179         'INCLUDE',
180         'LIB',
181         'MSDEVDIR',
182         'OS',
183         'PATHEXT',
184         'SystemRoot',
185         'TEMP',
186         'TMP',
187         'USERNAME',
188         'VXDOMNTOOLS',
189         'WINDIR',
190         'XYZZY'
191
192         'ENV',
193         'HOME',
194         'LANG',
195         'LANGUAGE',
196         'LOGNAME',
197         'MACHINE',
198         'OLDPWD',
199         'PWD',
200         'OPSYS',
201         'SHELL',
202         'TMPDIR',
203         'USER',
204     ]
205
206     print "  <environment>"
207     #keys = os.environ.keys()
208     keys = environ_keys
209     keys.sort()
210     for key in keys:
211         value = os.environ.get(key)
212         if value:
213             print "    <variable>"
214             print "      <name>%s</name>" % key
215             print "      <value>%s</value>" % value
216             print "    </variable>"
217     print "  </environment>"
218
219     command = '"%s" runtest.py -q -o - --xml %s' % (sys.executable, runtest_args)
220     #print command
221     os.system(command)
222     print "</scons_test_run>"
223
224 else:
225
226     def print_version_info(tag, module):
227         print "\t%s: v%s.%s, %s, by %s on %s" % (tag,
228                                                  module.__version__,
229                                                  module.__build__,
230                                                  module.__date__,
231                                                  module.__developer__,
232                                                  module.__buildsys__)
233
234     print "SCons by Steven Knight et al.:"
235     print_version_info("script", scons)
236     print_version_info("engine", SCons)
237
238     command = '"%s" runtest.py %s' % (sys.executable, runtest_args)
239     #print command
240     os.system(command)
241
242 # Local Variables:
243 # tab-width:4
244 # indent-tabs-mode:nil
245 # End:
246 # vim: set expandtab tabstop=4 shiftwidth=4: