Added fix for TeX includes with same name as subdirs.
[scons.git] / test / option-j.py
1 #!/usr/bin/env python
2 #
3 # __COPYRIGHT__
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #
24
25 """
26 This tests the -j command line option, and the num_jobs
27 SConscript settable option.
28 """
29
30 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
31
32 import os.path
33
34 import TestSCons
35
36 _python_ = TestSCons._python_
37
38 try:
39     import threading
40 except ImportError:
41     # if threads are not supported, then
42     # there is nothing to test
43     TestCmd.no_result()
44     sys.exit()
45
46
47 test = TestSCons.TestSCons()
48
49 test.write('build.py', r"""
50 import time
51 import sys
52 file = open(sys.argv[1], 'wb')
53 file.write(str(time.time()) + '\n')
54 time.sleep(1)
55 file.write(str(time.time()))
56 file.close()
57 """)
58
59 test.subdir('foo')
60
61 test.write(['foo','foo.in'], r"""
62 foo you
63 """)
64
65 test.write('SConstruct', """
66 MyBuild = Builder(action = r'%(_python_)s build.py $TARGETS')
67 env = Environment(BUILDERS = { 'MyBuild' : MyBuild })
68 env.Tool('install')
69 env.MyBuild(target = 'f1', source = 'f1.in')
70 env.MyBuild(target = 'f2', source = 'f2.in')
71
72 def copyn(env, target, source):
73     import shutil
74     import time
75     time.sleep(1)
76     for t in target:
77         shutil.copy(str(source[0]), str(t))
78
79 t = env.Command(target=['foo/foo1.out', 'foo/foo2.out'],
80                 source='foo/foo.in',
81                 action=copyn)
82 env.Install('out', t)
83 """ % locals())
84
85 def RunTest(args, extra):
86     """extra is used to make scons rebuild the output file"""
87     test.write('f1.in', 'f1.in'+extra)
88     test.write('f2.in', 'f2.in'+extra)
89
90     test.run(arguments = args)
91
92     str = test.read("f1")
93     start1,finish1 = list(map(float, str.split("\n")))
94
95     str = test.read("f2")
96     start2,finish2 = list(map(float, str.split("\n")))
97
98     return start2, finish1
99
100 # Test 2 parallel jobs.
101 # fail if the second file was not started
102 # before the first one was finished.
103 start2, finish1 = RunTest('-j 2 f1 f2', "first")
104 test.fail_test(not (start2 < finish1))
105
106 # re-run the test with the same input, fail if we don't
107 # get back the same times, which would indicate that
108 # SCons rebuilt the files even though nothing changed
109 s2, f1 = RunTest('-j 2 f1 f2', "first")
110 test.fail_test(start2 != s2)
111 test.fail_test(finish1 != f1)
112
113 # Test a single serial job.
114 # fail if the second file was started
115 # before the first one was finished
116 start2, finish1 = RunTest('f1 f2', "second")
117 test.fail_test(start2 < finish1)
118
119 # Make sure that a parallel build using a list builder
120 # succeeds.
121 test.run(arguments='-j 2 out')
122
123
124 # Test that we fall back and warn properly if there's no threading.py
125 # module (simulated), which is the case if this version of Python wasn't
126 # built with threading support.
127
128 test.subdir('pythonlib')
129
130 test.write(['pythonlib', 'threading.py'], """\
131 raise ImportError
132 """)
133
134 save_pythonpath = os.environ.get('PYTHONPATH', '')
135 os.environ['PYTHONPATH'] = test.workpath('pythonlib')
136
137 #start2, finish1 = RunTest('-j 2 f1, f2', "fifth")
138
139 test.write('f1.in', 'f1.in pythonlib\n')
140 test.write('f2.in', 'f2.in pythonlib\n')
141
142 test.run(arguments = "-j 2 f1 f2", stderr=None)
143
144 warn = \
145 """scons: warning: parallel builds are unsupported by this version of Python;
146 \tignoring -j or num_jobs option.
147 """
148 test.must_contain_all_lines(test.stderr(), [warn])
149
150 str = test.read("f1")
151 start1,finish1 = list(map(float, str.split("\n")))
152
153 str = test.read("f2")
154 start2,finish2 = list(map(float, str.split("\n")))
155
156 test.fail_test(start2 < finish1)
157
158 os.environ['PYTHONPATH'] = save_pythonpath
159
160
161 # Test SetJobs() with no -j:
162 test.write('SConstruct', """
163 MyBuild = Builder(action = r'%(_python_)s build.py $TARGETS')
164 env = Environment(BUILDERS = { 'MyBuild' : MyBuild })
165 env.Tool('install')
166 env.MyBuild(target = 'f1', source = 'f1.in')
167 env.MyBuild(target = 'f2', source = 'f2.in')
168
169 def copyn(env, target, source):
170     import shutil
171     import time
172     time.sleep(1)
173     for t in target:
174         shutil.copy(str(source[0]), str(t))
175
176 t = env.Command(target=['foo/foo1.out', 'foo/foo2.out'], source='foo/foo.in', action=copyn)
177 env.Install('out', t)
178
179 assert GetOption('num_jobs') == 1
180 SetOption('num_jobs', 2)
181 assert GetOption('num_jobs') == 2
182 """ % locals())
183
184 # This should be a parallel build because the SConscript sets jobs to 2.
185 # fail if the second file was not started
186 # before the first one was finished
187 start2, finish1 = RunTest('f1 f2', "third")
188 test.fail_test(not (start2 < finish1))
189
190 # Test SetJobs() with -j:
191 test.write('SConstruct', """
192 MyBuild = Builder(action = r'%(_python_)s build.py $TARGETS')
193 env = Environment(BUILDERS = { 'MyBuild' : MyBuild })
194 env.Tool('install')
195 env.MyBuild(target = 'f1', source = 'f1.in')
196 env.MyBuild(target = 'f2', source = 'f2.in')
197
198 def copyn(env, target, source):
199     import shutil
200     import time
201     time.sleep(1)
202     for t in target:
203         shutil.copy(str(source[0]), str(t))
204
205 t = env.Command(target=['foo/foo1.out', 'foo/foo2.out'], source='foo/foo.in', action=copyn)
206 env.Install('out', t)
207
208 assert GetOption('num_jobs') == 1
209 SetOption('num_jobs', 2)
210 assert GetOption('num_jobs') == 1
211 """ % locals())
212
213 # This should be a serial build since -j 1 overrides the call to SetJobs().
214 # fail if the second file was started
215 # before the first one was finished
216 start2, finish1 = RunTest('-j 1 f1 f2', "fourth")
217 test.fail_test(start2 < finish1)
218
219
220
221 test.pass_test()
222
223 # Local Variables:
224 # tab-width:4
225 # indent-tabs-mode:nil
226 # End:
227 # vim: set expandtab tabstop=4 shiftwidth=4: