Fix use of timestamps with --implicit-cache. (Anthony Roach)
[scons.git] / test / SourceSignatures.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 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
26
27 import imp
28 import os
29 import os.path
30 import time
31
32 import TestSCons
33
34 test = TestSCons.TestSCons()
35
36 test.write('SConstruct', """
37 def build(env, target, source):
38     open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
39 B = Builder(action = build)
40 env = Environment(BUILDERS = { 'B' : B })
41 env.B(target = 'f1.out', source = 'f1.in')
42 env.B(target = 'f2.out', source = 'f2.in')
43 env.B(target = 'f3.out', source = 'f3.in')
44 env.B(target = 'f4.out', source = 'f4.in')
45
46 SourceSignatures('timestamp')
47 """)
48
49 test.write('f1.in', "f1.in\n")
50 test.write('f2.in', "f2.in\n")
51 test.write('f3.in', "f3.in\n")
52 test.write('f4.in', "f4.in\n")
53
54 test.run(arguments = 'f1.out f3.out')
55
56 test.run(arguments = 'f1.out f2.out f3.out f4.out',
57          stdout = test.wrap_stdout("""\
58 scons: `f1.out' is up to date.
59 build("f2.out", "f2.in")
60 scons: `f3.out' is up to date.
61 build("f4.out", "f4.in")
62 """))
63
64 os.utime(test.workpath('f1.in'), 
65          (os.path.getatime(test.workpath('f1.in')),
66           os.path.getmtime(test.workpath('f1.in'))+10))
67 os.utime(test.workpath('f3.in'), 
68          (os.path.getatime(test.workpath('f3.in')),
69           os.path.getmtime(test.workpath('f3.in'))+10))
70
71 test.run(arguments = 'f1.out f2.out f3.out f4.out',
72          stdout = test.wrap_stdout("""\
73 build("f1.out", "f1.in")
74 scons: `f2.out' is up to date.
75 build("f3.out", "f3.in")
76 scons: `f4.out' is up to date.
77 """))
78
79 test.write('SConstruct', """
80 def build(env, target, source):
81     open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
82 B = Builder(action = build)
83 env = Environment(BUILDERS = { 'B' : B })
84 env.B(target = 'f1.out', source = 'f1.in')
85 env.B(target = 'f2.out', source = 'f2.in')
86 env.B(target = 'f3.out', source = 'f3.in')
87 env.B(target = 'f4.out', source = 'f4.in')
88
89 SourceSignatures('MD5')
90 """)
91
92 test.write('f1.in', "f1.in\n")
93 test.write('f2.in', "f2.in\n")
94 test.write('f3.in', "f3.in\n")
95 test.write('f4.in', "f4.in\n")
96
97 test.run(arguments = 'f1.out f3.out')
98
99 test.run(arguments = 'f1.out f2.out f3.out f4.out',
100          stdout = test.wrap_stdout("""\
101 scons: `f1.out' is up to date.
102 build("f2.out", "f2.in")
103 scons: `f3.out' is up to date.
104 build("f4.out", "f4.in")
105 """))
106
107 os.utime(test.workpath('f1.in'), 
108          (os.path.getatime(test.workpath('f1.in')),
109           os.path.getmtime(test.workpath('f1.in'))+10))
110 os.utime(test.workpath('f3.in'), 
111          (os.path.getatime(test.workpath('f3.in')),
112           os.path.getmtime(test.workpath('f3.in'))+10))
113
114 test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
115
116 test.write('SConstruct', """
117 def build(env, target, source):
118     open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
119 B = Builder(action = build)
120 env = Environment(BUILDERS = { 'B' : B })
121 env.B(target = 'f1.out', source = 'f1.in')
122 env.B(target = 'f2.out', source = 'f2.in')
123 env.B(target = 'f3.out', source = 'f3.in')
124 env.B(target = 'f4.out', source = 'f4.in')
125 """)
126
127 test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
128
129 test.write('SConstruct', """
130 def build(env, target, source):
131     open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
132 B = Builder(action = build)
133 env = Environment(BUILDERS = { 'B' : B })
134 env2 = env.Copy()
135 env2.SourceSignatures('MD5')
136 env.B(target = 'f5.out', source = 'f5.in')
137 env.B(target = 'f6.out', source = 'f6.in')
138 env2.B(target = 'f7.out', source = 'f7.in')
139 env2.B(target = 'f8.out', source = 'f8.in')
140
141 SourceSignatures('timestamp')
142 """)
143
144 test.write('f5.in', "f5.in\n")
145 test.write('f6.in', "f6.in\n")
146 test.write('f7.in', "f7.in\n")
147 test.write('f8.in', "f8.in\n")
148
149 test.run(arguments = 'f5.out f7.out')
150
151 test.run(arguments = 'f5.out f6.out f7.out f8.out',
152          stdout = test.wrap_stdout("""\
153 scons: `f5.out' is up to date.
154 build("f6.out", "f6.in")
155 scons: `f7.out' is up to date.
156 build("f8.out", "f8.in")
157 """))
158
159 os.utime(test.workpath('f5.in'), 
160          (os.path.getatime(test.workpath('f5.in')),
161           os.path.getmtime(test.workpath('f5.in'))+10))
162 os.utime(test.workpath('f7.in'), 
163          (os.path.getatime(test.workpath('f7.in')),
164           os.path.getmtime(test.workpath('f7.in'))+10))
165
166 test.run(arguments = 'f5.out f6.out f7.out f8.out',
167          stdout = test.wrap_stdout("""\
168 build("f5.out", "f5.in")
169 scons: `f6.out' is up to date.
170 scons: `f7.out' is up to date.
171 scons: `f8.out' is up to date.
172 """))
173
174 test.up_to_date(arguments = 'f5.out f6.out f7.out f8.out')
175
176 # Ensure that switching signature types causes a rebuild:
177 test.write('SConstruct', """
178 SourceSignatures('MD5')
179
180 def build(env, target, source):
181     open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
182 B = Builder(action = build)
183 env = Environment(BUILDERS = { 'B' : B })
184 env.B(target = 'switch.out', source = 'switch.in')
185 """)
186
187 test.write('switch.in', "switch.in\n")
188
189 test.run(arguments = 'switch.out',
190          stdout = test.wrap_stdout("""\
191 build("switch.out", "switch.in")
192 """))
193
194 test.up_to_date(arguments = 'switch.out')
195
196 test.write('SConstruct', """
197 SourceSignatures('timestamp')
198
199 def build(env, target, source):
200     open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
201 B = Builder(action = build)
202 env = Environment(BUILDERS = { 'B' : B })
203 env.B(target = 'switch.out', source = 'switch.in')
204 """)
205
206 test.run(arguments = 'switch.out',
207          stdout = test.wrap_stdout("""\
208 build("switch.out", "switch.in")
209 """))
210
211 test.up_to_date(arguments = 'switch.out')
212
213 test.write('SConstruct', """
214 SourceSignatures('MD5')
215
216 def build(env, target, source):
217     open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
218 B = Builder(action = build)
219 env = Environment(BUILDERS = { 'B' : B })
220 env.B(target = 'switch.out', source = 'switch.in')
221 """)
222
223 test.run(arguments = 'switch.out',
224          stdout = test.wrap_stdout("""\
225 build("switch.out", "switch.in")
226 """))
227
228 test.up_to_date(arguments = 'switch.out')
229
230 test.write('switch.in', "switch.in 2\n")
231
232 test.run(arguments = 'switch.out',
233          stdout = test.wrap_stdout("""\
234 build("switch.out", "switch.in")
235 """))
236
237
238 # Test both implicit_cache and timestamp signatures at the same time:
239 test.write('SConstruct', """
240 SetOption('implicit_cache', 1)
241 SourceSignatures('timestamp')
242
243 def build(env, target, source):
244     open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
245 B = Builder(action = build)
246 env = Environment(BUILDERS = { 'B' : B })
247 env.B(target = 'both.out', source = 'both.in')
248 """)
249
250 test.write('both.in', "both.in 1\n")
251
252 test.run(arguments = 'both.out',
253          stdout = test.wrap_stdout("""\
254 build("both.out", "both.in")
255 """))
256
257 time.sleep(2)
258
259 test.write('both.in', "both.in 2\n")
260
261 test.run(arguments = 'both.out',
262          stdout = test.wrap_stdout("""\
263 build("both.out", "both.in")
264 """))
265
266 time.sleep(2)
267
268 test.write('both.in', "both.in 3\n")
269
270 test.run(arguments = 'both.out',
271          stdout = test.wrap_stdout("""\
272 build("both.out", "both.in")
273 """))
274
275 time.sleep(2)
276
277 test.write('both.in', "both.in 4\n")
278
279 test.run(arguments = 'both.out',
280          stdout = test.wrap_stdout("""\
281 build("both.out", "both.in")
282 """))
283
284 time.sleep(2)
285
286
287 test.up_to_date(arguments = 'both.out')
288
289 test.pass_test()