Extend SConstruct et al. to build .zip files, and to build the scons-src package...
[scons.git] / runtest.py
1 #!/usr/bin/env python
2 #
3 # runtests.py - wrapper script for running SCons tests
4 #
5 # This script mainly exists to set PYTHONPATH to the right list of
6 # directories to test the SCons modules.
7 #
8 # By default, it directly uses the modules in the local tree:
9 # ./src/ (source files we ship) and ./etc/ (other modules we don't)
10 #
11 # When "-b aegis" is specified, it assumes it's in a directory
12 # in which an Aegis build (aeb) has been performed, and sets
13 # PYTHONPATH so that it *only* references the modules that have
14 # unpacked from the built packages, to test whether the packages
15 # are good.
16 #
17 # Options:
18 #
19 #       -a              Run all tests; does a virtual 'find' for
20 #                       all SCons tests under the current directory.
21 #
22 #       -d              Debug.  Runs the script under the Python
23 #                       debugger (pdb.py) so you don't have to
24 #                       muck with PYTHONPATH yourself.
25 #
26 #       -q              Quiet.  By default, runtest.py prints the
27 #                       command line it will execute before
28 #                       executing it.  This suppresses that print.
29 #
30 #       -p package      Test against the specified package.
31 #
32 # (Note:  There used to be a -v option that specified the SCons
33 # version to be tested, when we were installing in a version-specific
34 # library directory.  If we ever resurrect that as the default, then
35 # you can find the appropriate code in the 0.04 version of this script,
36 # rather than reinventing that wheel.)
37 #
38
39 import getopt
40 import os
41 import os.path
42 import re
43 import string
44 import sys
45
46 all = 0
47 debug = ''
48 tests = []
49 printcmd = 1
50 package = None
51
52 if sys.platform == 'win32':
53     lib_dir = os.path.join(sys.exec_prefix, "lib")
54 else:
55     lib_dir = os.path.join(sys.exec_prefix, "lib", "python" + sys.version[0:3])
56
57 opts, tests = getopt.getopt(sys.argv[1:], "adqp:",
58                             ['all', 'debug', 'quiet', 'package='])
59
60 for o, a in opts:
61     if o == '-a' or o == '--all': all = 1
62     elif o == '-d' or o == '--debug': debug = os.path.join(lib_dir, "pdb.py")
63     elif o == '-q' or o == '--quiet': printcmd = 0
64     elif o == '-p' or o == '--package': package = a
65
66 cwd = os.getcwd()
67
68 if tests:
69     map(os.path.abspath, tests)
70 elif all:
71     def find_Test_py(arg, dirname, names):
72         global tests
73         n = filter(lambda n: n[-8:] == "Tests.py", names)
74         tests.extend(map(lambda x,d=dirname: os.path.join(d, x), n))
75     os.path.walk('src', find_Test_py, 0)
76
77     def find_py(arg, dirname, names):
78         global tests
79         n = filter(lambda n: n[-3:] == ".py", names)
80         tests.extend(map(lambda x,d=dirname: os.path.join(d, x), n))
81     os.path.walk('test', find_py, 0)
82
83     tests.sort()
84
85 if package:
86
87     dir = {
88         'deb'        : 'usr',
89         'rpm'        : 'usr',
90         'src-tar-gz' : '',
91         'src-zip'    : '',
92         'tar-gz'     : '',
93         'zip'        : '',
94     }
95
96     if not dir.has_key(package):
97         sys.stderr.write("Unknown package '%s'\n" % package)
98         sys.exit(2)
99
100     test_dir = os.path.join(cwd, 'build', 'test-%s' % package)
101
102     if sys.platform == 'win32':
103         scons_dir = os.path.join(test_dir, dir[package], 'Scripts')
104         lib_dir = os.path.join(test_dir, dir[package])
105     else:
106         scons_dir = os.path.join(test_dir, dir[package], 'bin')
107         lib_dir = os.path.join(test_dir, dir[package], 'lib', 'scons')
108
109 else:
110
111     scons_dir = os.path.join(cwd, 'src', 'script')
112
113     lib_dir = os.path.join(cwd, 'src', 'engine')
114
115 os.environ['PYTHONPATH'] = lib_dir + \
116                            os.pathsep + \
117                            os.path.join(cwd, 'build', 'etc') + \
118                            os.pathsep + \
119                            os.path.join(cwd, 'etc')
120
121 os.chdir(scons_dir)
122
123 fail = []
124 no_result = []
125
126 for path in tests:
127     if os.path.isabs(path):
128         abs = path
129     else:
130         abs = os.path.join(cwd, path)
131     cmd = string.join(["python", debug, abs], " ")
132     if printcmd:
133         print cmd
134     s = os.system(cmd)
135     if s == 1 or s == 256:
136         fail.append(path)
137     elif s == 2 or s == 512:
138         no_result.append(path)
139     elif s != 0:
140         print "Unexpected exit status %d" % s
141
142 if len(tests) != 1:
143     if fail:
144         if len(fail) == 1:
145             str = "test"
146         else:
147             str = "%d tests" % len(fail)
148         print "\nFailed the following %s:" % str
149         print "\t", string.join(fail, "\n\t")
150     if no_result:
151         if len(no_result) == 1:
152             str = "test"
153         else:
154             str = "%d tests" % len(no_result)
155         print "\nNO RESULT from the following %s:" % str
156         print "\t", string.join(no_result, "\n\t")
157
158 sys.exit(len(fail) + len(no_result))