08cfb4f58e6cb35d16e4679df0f4270c324732a3
[scons.git] / QMTest / TestRuntest.py
1 """
2 TestRuntest.py:  a testing framework for the runtest.py command used to
3 invoke SCons tests.
4
5 A TestRuntest environment object is created via the usual invocation:
6
7     test = TestRuntest()
8
9 TestRuntest is a subclass of TestCommon, which is in turn is a subclass
10 of TestCmd), and hence has available all of the methods and attributes
11 from those classes, as well as any overridden or additional methods or
12 attributes defined in this subclass.
13 """
14
15 # __COPYRIGHT__
16
17 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
18
19 import os
20 import os.path
21 import string
22 import shutil
23 import sys
24
25 from TestCommon import *
26 from TestCommon import __all__
27
28 __all__.extend([ 'TestRuntest',
29                  'python',
30                  '_python_',
31                ])
32
33 python = python_executable
34 _python_ = '"' + python_executable + '"'
35
36
37 failing_test_template = """\
38 import sys
39 sys.stdout.write('FAILING TEST STDOUT\\n')
40 sys.stderr.write('FAILING TEST STDERR\\n')
41 sys.exit(1)
42 """
43
44 no_result_test_template = """\
45 import sys
46 sys.stdout.write('NO RESULT TEST STDOUT\\n')
47 sys.stderr.write('NO RESULT TEST STDERR\\n')
48 sys.exit(2)
49 """
50
51 passing_test_template = """\
52 import sys
53 sys.stdout.write('PASSING TEST STDOUT\\n')
54 sys.stderr.write('PASSING TEST STDERR\\n')
55 sys.exit(0)
56 """
57
58 fake_scons_py = """
59 __version__ = '1.2.3'
60 __build__ = 'D123'
61 __buildsys__ = 'fake_system'
62 __date__ = 'Jan 1 1970'
63 __developer__ = 'Anonymous'
64 """
65
66 fake___init___py = """
67 __version__ = '4.5.6'
68 __build__ = 'D456'
69 __buildsys__ = 'another_fake_system'
70 __date__ = 'Dec 31 1999'
71 __developer__ = 'John Doe'
72 """
73
74 class TestRuntest(TestCommon):
75     """Class for testing the runtest.py script.
76
77     This provides a common place for initializing Runtest tests,
78     eliminating the need to begin every test with the same repeated
79     initializations.
80     """
81
82     def __init__(self, **kw):
83         """Initialize a Runtest testing object.
84
85         If they're not overridden by keyword arguments, this
86         initializes the object with the following default values:
87
88                 program = 'runtest.py'
89                 interpreter = ['python', '-tt']
90                 match = match_exact
91                 workdir = ''
92
93         The workdir value means that, by default, a temporary
94         workspace directory is created for a TestRuntest environment.
95         The superclass TestCommon.__init__() will change directory (chdir)
96         to the workspace directory, so an explicit "chdir = '.'" on all
97         of the run() method calls is not necessary.  This initialization
98         also copies the runtest.py and QMTest/ subdirectory tree to the
99         temporary directory, duplicating how this test infrastructure
100         appears in a normal workspace.
101         """
102         set_workpath_runtest = None
103         if not kw.has_key('program'):
104             kw['program'] = 'runtest.py'
105             set_workpath_runtest = 1
106         if not kw.has_key('interpreter'):
107             kw['interpreter'] = [python, '-tt']
108         if not kw.has_key('match'):
109             kw['match'] = match_exact
110         if not kw.has_key('workdir'):
111             kw['workdir'] = ''
112
113         try:
114             noqmtest = kw['noqmtest']
115         except KeyError:
116             noqmtest = 0
117         else:
118             del kw['noqmtest']
119
120         orig_cwd = os.getcwd()
121         apply(TestCommon.__init__, [self], kw)
122   
123         if not noqmtest:
124             qmtest = self.where_is('qmtest')
125             if not qmtest:
126                 self.skip_test("Could not find 'qmtest'; skipping test(s).\n")
127
128         things_to_copy = [
129             'runtest.py',
130             'QMTest',
131         ]
132
133         dirs = [os.environ.get('SCONS_RUNTEST_DIR', orig_cwd)]
134         
135         spe = os.environ.get('SCONS_SOURCE_PATH_EXECUTABLE', orig_cwd)
136         for d in string.split(spe, os.pathsep):
137             dirs.append(os.path.join(d, 'build'))
138             dirs.append(d)
139
140         for thing in things_to_copy:
141             for dir in dirs:
142                 t = os.path.join(dir, thing)
143                 if os.path.exists(t):
144                     if os.path.isdir(t):
145                         copy_func = shutil.copytree
146                     else:
147                         copy_func = shutil.copyfile
148                     copy_func(t, self.workpath(thing))
149                     break
150
151         if set_workpath_runtest:
152             self.program_set(self.workpath('runtest.py'))
153
154         for key in os.environ.keys():
155             if key[:5] == 'AEGIS':
156                 os.environ[key] = ''
157
158         os.environ['PYTHONPATH'] = ''
159         os.environ['SCONS_SOURCE_PATH_EXECUTABLE'] = ''
160
161     def write_fake_scons_source_tree(self):
162         os.mkdir('src')
163         os.mkdir('src/script')
164         self.write('src/script/scons.py', fake_scons_py)
165
166         os.mkdir('src/engine')
167         os.mkdir('src/engine/SCons')
168         self.write('src/engine/SCons/__init__.py', fake___init___py)
169         os.mkdir('src/engine/SCons/Script')
170         self.write('src/engine/SCons/Script/__init__.py', fake___init___py)
171
172     def write_failing_test(self, name):
173         self.write(name, failing_test_template)
174
175     def write_no_result_test(self, name):
176         self.write(name, no_result_test_template)
177
178     def write_passing_test(self, name):
179         self.write(name, passing_test_template)
180
181 # Local Variables:
182 # tab-width:4
183 # indent-tabs-mode:nil
184 # End:
185 # vim: set expandtab tabstop=4 shiftwidth=4: