Rework implicit dependency scanning for relative CPPPATH values.
[scons.git] / src / engine / SCons / Node / NodeTests.py
1 #
2 # Copyright (c) 2001 Steven Knight
3 #
4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #
23
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
25
26 import os
27 import sys
28 import unittest
29
30 import SCons.Errors
31 import SCons.Node
32
33
34
35 built_it = None
36 built_target =  None
37 built_source =  None
38 cycle_detected = None
39
40 class Builder:
41     def execute(self, **kw):
42         global built_it, built_target, built_source
43         built_it = 1
44         built_target = kw['target']
45         built_source = kw['source']
46         return 0
47     def get_contents(self, env, dir):
48         return 7
49
50 class FailBuilder:
51     def execute(self, **kw):
52         return 1
53
54 class Environment:
55     def Dictionary(self, *args):
56         pass
57
58
59
60 class NodeTestCase(unittest.TestCase):
61
62     def test_BuildException(self):
63         """Test throwing an exception on build failure.
64         """
65         node = SCons.Node.Node()
66         node.builder_set(FailBuilder())
67         node.env_set(Environment())
68         try:
69             node.build()
70         except SCons.Errors.BuildError:
71             pass
72         else:
73             raise TestFailed, "did not catch expected BuildError"
74
75     def test_build(self):
76         """Test building a node
77         """
78         class MyNode(SCons.Node.Node):
79             def __str__(self):
80                 return self.path
81         # Make sure it doesn't blow up if no builder is set.
82         node = MyNode()
83         node.build()
84         assert built_it == None
85
86         node = MyNode()
87         node.builder_set(Builder())
88         node.env_set(Environment())
89         node.path = "xxx"
90         node.sources = ["yyy", "zzz"]
91         node.build()
92         assert built_it
93         assert type(built_target) == type(MyNode()), type(built_target)
94         assert str(built_target) == "xxx", str(built_target)
95         assert built_source == ["yyy", "zzz"], built_source
96
97     def test_builder_set(self):
98         """Test setting a Node's Builder
99         """
100         node = SCons.Node.Node()
101         b = Builder()
102         node.builder_set(b)
103         assert node.builder == b
104
105     def test_builder_sig_adapter(self):
106         """Test the node's adapter for builder signatures
107         """
108         node = SCons.Node.Node()
109         node.builder_set(Builder())
110         node.env_set(Environment())
111         c = node.builder_sig_adapter().get_contents()
112         assert c == 7, c
113
114     def test_current(self):
115         """Test the default current() method
116         """
117         node = SCons.Node.Node()
118         assert node.current() is None
119
120     def test_env_set(self):
121         """Test setting a Node's Environment
122         """
123         node = SCons.Node.Node()
124         e = Environment()
125         node.env_set(e)
126         assert node.env == e
127
128     def test_set_bsig(self):
129         """Test setting a Node's signature
130         """
131         node = SCons.Node.Node()
132         node.set_bsig('www')
133         assert node.bsig == 'www'
134
135     def test_get_bsig(self):
136         """Test fetching a Node's signature
137         """
138         node = SCons.Node.Node()
139         node.set_bsig('xxx')
140         assert node.get_bsig() == 'xxx'
141
142     def test_set_csig(self):
143         """Test setting a Node's signature
144         """
145         node = SCons.Node.Node()
146         node.set_csig('yyy')
147         assert node.csig == 'yyy'
148
149     def test_get_csig(self):
150         """Test fetching a Node's signature
151         """
152         node = SCons.Node.Node()
153         node.set_csig('zzz')
154         assert node.get_csig() == 'zzz'
155
156     def test_add_dependency(self):
157         """Test adding dependencies to a Node's list.
158         """
159         node = SCons.Node.Node()
160         assert node.depends == []
161
162         zero = SCons.Node.Node()
163         try:
164             node.add_dependency(zero)
165         except TypeError:
166             pass
167         else:
168             assert 0
169
170         one = SCons.Node.Node()
171         two = SCons.Node.Node()
172         three = SCons.Node.Node()
173         four = SCons.Node.Node()
174
175         node.add_dependency([one])
176         assert node.depends == [one]
177         node.add_dependency([two, three])
178         assert node.depends == [one, two, three]
179         node.add_dependency([three, four, one])
180         assert node.depends == [one, two, three, four]
181
182         assert zero.get_parents() == []
183         assert one.get_parents() == [node]
184         assert two.get_parents() == [node]
185         assert three.get_parents() == [node]
186         assert four.get_parents() == [node]
187
188
189     def test_add_source(self):
190         """Test adding sources to a Node's list.
191         """
192         node = SCons.Node.Node()
193         assert node.sources == []
194
195         zero = SCons.Node.Node()
196         try:
197             node.add_source(zero)
198         except TypeError:
199             pass
200         else:
201             assert 0
202
203         one = SCons.Node.Node()
204         two = SCons.Node.Node()
205         three = SCons.Node.Node()
206         four = SCons.Node.Node()
207
208         node.add_source([one])
209         assert node.sources == [one]
210         node.add_source([two, three])
211         assert node.sources == [one, two, three]
212         node.add_source([three, four, one])
213         assert node.sources == [one, two, three, four]
214
215         assert zero.get_parents() == []
216         assert one.get_parents() == [node]
217         assert two.get_parents() == [node]
218         assert three.get_parents() == [node]
219         assert four.get_parents() == [node]
220
221     def test_add_implicit(self):
222         """Test adding implicit (scanned) dependencies to a Node's list.
223         """
224         node = SCons.Node.Node()
225         assert node.implicit == {}
226
227         zero = SCons.Node.Node()
228         try:
229             node.add_source(zero)
230         except TypeError:
231             pass
232         else:
233             assert 0
234
235         one = SCons.Node.Node()
236         two = SCons.Node.Node()
237         three = SCons.Node.Node()
238         four = SCons.Node.Node()
239
240         node.add_implicit([one], 1)
241         assert node.implicit[1] == [one]
242         node.add_implicit([two, three], 1)
243         assert node.implicit[1] == [one, two, three]
244         node.add_implicit([three, four, one], 1)
245         assert node.implicit[1] == [one, two, three, four]
246
247         assert zero.get_parents() == []
248         assert one.get_parents() == [node]
249         assert two.get_parents() == [node]
250         assert three.get_parents() == [node]
251         assert four.get_parents() == [node]
252
253         node.add_implicit([one], 2)
254         node.add_implicit([two, three], 3)
255         node.add_implicit([three, four, one], 4)
256
257         assert node.implicit[1] == [one, two, three, four]
258         assert node.implicit[2] == [one]
259         assert node.implicit[3] == [two, three]
260         assert node.implicit[4] == [three, four, one]
261
262     def test_children(self):
263         """Test fetching the "children" of a Node.
264         """
265         node = SCons.Node.Node()
266         one = SCons.Node.Node()
267         two = SCons.Node.Node()
268         three = SCons.Node.Node()
269         four = SCons.Node.Node()
270         five = SCons.Node.Node()
271         six = SCons.Node.Node()
272
273         node.add_source([one, two, three])
274         node.add_dependency([four, five, six])
275         kids = node.children()
276         assert len(kids) == 6
277         assert one in kids
278         assert two in kids
279         assert three in kids
280         assert four in kids
281         assert five in kids
282         assert six in kids
283
284     def test_add_parent(self):
285         """Test adding parents to a Node."""
286         node = SCons.Node.Node()
287         parent = SCons.Node.Node()
288         node._add_parent(parent)
289         assert node.get_parents() == [parent]
290         node._add_parent(parent)
291         assert node.get_parents() == [parent]
292
293     def test_state(self):
294         """Test setting and getting the state of a node
295         """
296         node = SCons.Node.Node()
297         assert node.get_state() == None
298         node.set_state(SCons.Node.executing)
299         assert node.get_state() == SCons.Node.executing
300         assert SCons.Node.pending < SCons.Node.executing
301         assert SCons.Node.executing < SCons.Node.up_to_date
302         assert SCons.Node.up_to_date < SCons.Node.executed
303         assert SCons.Node.executed < SCons.Node.failed
304
305     def test_walker(self):
306         """Test walking a Node tree.
307         """
308
309         class MyNode(SCons.Node.Node):
310             def __init__(self, name):
311                 SCons.Node.Node.__init__(self)
312                 self.name = name
313
314         n1 = MyNode("n1")
315
316         nw = SCons.Node.Walker(n1)
317         assert not nw.is_done()
318         assert nw.next().name ==  "n1"
319         assert nw.is_done()
320         assert nw.next() == None
321
322         n2 = MyNode("n2")
323         n3 = MyNode("n3")
324         n1.add_source([n2, n3])
325
326         nw = SCons.Node.Walker(n1)
327         assert nw.next().name ==  "n2"
328         assert nw.next().name ==  "n3"
329         assert nw.next().name ==  "n1"
330         assert nw.next() == None
331
332         n4 = MyNode("n4")
333         n5 = MyNode("n5")
334         n6 = MyNode("n6")
335         n7 = MyNode("n7")
336         n2.add_source([n4, n5])
337         n3.add_dependency([n6, n7])
338
339         nw = SCons.Node.Walker(n1)
340         assert nw.next().name ==  "n4"
341         assert nw.next().name ==  "n5"
342         assert nw.history.has_key(n2)
343         assert nw.next().name ==  "n2"
344         assert nw.next().name ==  "n6"
345         assert nw.next().name ==  "n7"
346         assert nw.history.has_key(n3)
347         assert nw.next().name ==  "n3"
348         assert nw.history.has_key(n1)
349         assert nw.next().name ==  "n1"
350         assert nw.next() == None
351
352         n8 = MyNode("n8")
353         n8.add_dependency([n3])
354         n7.add_dependency([n8])
355
356         def cycle(node, stack):
357             global cycle_detected
358             cycle_detected = 1
359
360         global cycle_detected
361
362         nw = SCons.Node.Walker(n3, cycle_func = cycle)
363         n = nw.next()
364         assert n.name == "n6", n.name
365         n = nw.next()
366         assert n.name == "n8", n.name
367         assert cycle_detected
368         cycle_detected = None
369         n = nw.next()
370         assert n.name == "n7", n.name
371         n = nw.next()
372         assert nw.next() == None
373
374     def test_children_are_executed(self):
375         n1 = SCons.Node.Node()
376         n2 = SCons.Node.Node()
377         n3 = SCons.Node.Node()
378         n4 = SCons.Node.Node()
379
380         n4.add_source([n3])
381         n3.add_source([n1, n2])
382
383         assert not n4.children_are_executed()
384         assert not n3.children_are_executed()
385         assert n2.children_are_executed()
386         assert n1.children_are_executed()
387
388         n1.set_state(SCons.Node.executed)
389         assert not n4.children_are_executed()
390         assert not n3.children_are_executed()
391         assert n2.children_are_executed()
392         assert n1.children_are_executed()
393
394         n2.set_state(SCons.Node.executed)
395         assert not n4.children_are_executed()
396         assert n3.children_are_executed()
397         assert n2.children_are_executed()
398         assert n1.children_are_executed()
399
400         n3.set_state(SCons.Node.executed)
401         assert n4.children_are_executed()
402         assert n3.children_are_executed()
403         assert n2.children_are_executed()
404         assert n1.children_are_executed()
405
406
407
408
409 if __name__ == "__main__":
410     suite = unittest.makeSuite(NodeTestCase, 'test_')
411     if not unittest.TextTestRunner().run(suite).wasSuccessful():
412         sys.exit(1)