2 # Copyright (c) 2001, 2002 Steven Knight
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:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
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.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
41 def execute(self, **kw):
42 global built_it, built_target, built_source
44 built_target = kw['target']
45 built_source = kw['source']
47 def get_contents(self, env):
50 class NoneBuilder(Builder):
51 def execute(self, **kw):
52 apply(Builder.execute, (self,), kw)
55 class ListBuilder(Builder):
56 def __init__(self, *nodes):
58 def execute(self, **kw):
59 if hasattr(self, 'status'):
63 kw['target'] = self.nodes[0]
64 self.status = apply(Builder.execute, (self,), kw)
67 def execute(self, **kw):
71 def execute(self, **kw):
72 raise SCons.Errors.BuildError
75 def execute(self, **kw):
79 def Dictionary(self, *args):
84 class NodeTestCase(unittest.TestCase):
86 def test_BuildException(self):
87 """Test throwing an exception on build failure.
89 node = SCons.Node.Node()
90 node.builder_set(FailBuilder())
91 node.env_set(Environment())
94 except SCons.Errors.BuildError:
97 raise TestFailed, "did not catch expected BuildError"
99 node = SCons.Node.Node()
100 node.builder_set(ExceptBuilder())
101 node.env_set(Environment())
104 except SCons.Errors.BuildError:
107 raise TestFailed, "did not catch expected BuildError"
109 node = SCons.Node.Node()
110 node.builder_set(ExceptBuilder2())
111 node.env_set(Environment())
114 except SCons.Errors.BuildError, e:
115 # On a generic (non-BuildError) exception from a Builder,
116 # the Node should throw a BuildError exception with
117 # the args set to the exception value, type, and traceback.
118 assert len(e.args) == 3, `e.args`
119 assert e.args[0] == 'foo', e.args[0]
120 assert e.args[1] is None
121 assert type(e.args[2]) is type(sys.exc_traceback), e.args[2]
123 raise TestFailed, "did not catch expected BuildError"
125 def test_build(self):
126 """Test building a node
130 class MyNode(SCons.Node.Node):
131 def __init__(self, **kw):
132 apply(SCons.Node.Node.__init__, (self,), kw)
133 self.prepare_count = 0
137 self.prepare_count = self.prepare_count+ 1
138 # Make sure it doesn't blow up if no builder is set.
141 assert built_it == None
144 node.builder_set(Builder())
145 node.env_set(Environment())
147 node.sources = ["yyy", "zzz"]
150 assert type(built_target) == type(MyNode()), type(built_target)
151 assert str(built_target) == "xxx", str(built_target)
152 assert built_source == ["yyy", "zzz"], built_source
156 node.builder_set(NoneBuilder())
157 node.env_set(Environment())
159 node.sources = ["rrr", "sss"]
162 assert type(built_target) == type(MyNode()), type(built_target)
163 assert str(built_target) == "qqq", str(built_target)
164 assert built_source == ["rrr", "sss"], built_source
168 lb = ListBuilder(fff, ggg)
176 fff.sources = ["hhh", "iii"]
177 ggg.sources = ["hhh", "iii"]
183 assert ggg.prepare_count== 1, ggg.prepare_count
184 assert type(built_target) == type(MyNode()), type(built_target)
185 assert str(built_target) == "fff", str(built_target)
186 assert built_source == ["hhh", "iii"], built_source
188 delattr(lb, 'status')
189 fff.prepare_count = 0
190 ggg.prepare_count = 0
196 assert fff.prepare_count== 1, fff.prepare_count
197 assert type(built_target) == type(MyNode()), type(built_target)
198 assert str(built_target) == "fff", str(built_target)
199 assert built_source == ["hhh", "iii"], built_source
201 def test_builder_set(self):
202 """Test setting a Node's Builder
204 node = SCons.Node.Node()
207 assert node.builder == b
209 def test_builder_sig_adapter(self):
210 """Test the node's adapter for builder signatures
212 node = SCons.Node.Node()
213 node.builder_set(Builder())
214 node.env_set(Environment())
215 c = node.builder_sig_adapter().get_contents()
218 def test_current(self):
219 """Test the default current() method
221 node = SCons.Node.Node()
222 assert node.current() is None
224 def test_env_set(self):
225 """Test setting a Node's Environment
227 node = SCons.Node.Node()
232 def test_set_bsig(self):
233 """Test setting a Node's signature
235 node = SCons.Node.Node()
237 assert node.bsig == 'www'
239 def test_get_bsig(self):
240 """Test fetching a Node's signature
242 node = SCons.Node.Node()
244 assert node.get_bsig() == 'xxx'
246 def test_set_csig(self):
247 """Test setting a Node's signature
249 node = SCons.Node.Node()
251 assert node.csig == 'yyy'
253 def test_get_csig(self):
254 """Test fetching a Node's signature
256 node = SCons.Node.Node()
258 assert node.get_csig() == 'zzz'
260 def test_store_sigs(self):
261 """Test calling the method to store signatures
263 node = SCons.Node.Node()
266 def test_set_precious(self):
267 """Test setting a Node's precious value
269 node = SCons.Node.Node()
273 assert node.precious == 7
275 def test_add_dependency(self):
276 """Test adding dependencies to a Node's list.
278 node = SCons.Node.Node()
279 assert node.depends == []
281 zero = SCons.Node.Node()
283 node.add_dependency(zero)
289 one = SCons.Node.Node()
290 two = SCons.Node.Node()
291 three = SCons.Node.Node()
292 four = SCons.Node.Node()
294 node.add_dependency([one])
295 assert node.depends == [one]
296 node.add_dependency([two, three])
297 assert node.depends == [one, two, three]
298 node.add_dependency([three, four, one])
299 assert node.depends == [one, two, three, four]
301 assert zero.get_parents() == []
302 assert one.get_parents() == [node]
303 assert two.get_parents() == [node]
304 assert three.get_parents() == [node]
305 assert four.get_parents() == [node]
308 def test_add_source(self):
309 """Test adding sources to a Node's list.
311 node = SCons.Node.Node()
312 assert node.sources == []
314 zero = SCons.Node.Node()
316 node.add_source(zero)
322 one = SCons.Node.Node()
323 two = SCons.Node.Node()
324 three = SCons.Node.Node()
325 four = SCons.Node.Node()
327 node.add_source([one])
328 assert node.sources == [one]
329 node.add_source([two, three])
330 assert node.sources == [one, two, three]
331 node.add_source([three, four, one])
332 assert node.sources == [one, two, three, four]
334 assert zero.get_parents() == []
335 assert one.get_parents() == [node]
336 assert two.get_parents() == [node]
337 assert three.get_parents() == [node]
338 assert four.get_parents() == [node]
340 def test_add_implicit(self):
341 """Test adding implicit (scanned) dependencies to a Node's list.
343 node = SCons.Node.Node()
344 assert node.implicit == {}
346 zero = SCons.Node.Node()
348 node.add_source(zero)
354 one = SCons.Node.Node()
355 two = SCons.Node.Node()
356 three = SCons.Node.Node()
357 four = SCons.Node.Node()
359 node.add_implicit([one], 1)
360 assert node.implicit[1] == [one]
361 node.add_implicit([two, three], 1)
362 assert node.implicit[1] == [one, two, three]
363 node.add_implicit([three, four, one], 1)
364 assert node.implicit[1] == [one, two, three, four]
366 assert zero.get_parents() == []
367 assert one.get_parents() == [node]
368 assert two.get_parents() == [node]
369 assert three.get_parents() == [node]
370 assert four.get_parents() == [node]
372 node.add_implicit([one], 2)
373 node.add_implicit([two, three], 3)
374 node.add_implicit([three, four, one], 4)
376 assert node.implicit[1] == [one, two, three, four]
377 assert node.implicit[2] == [one]
378 assert node.implicit[3] == [two, three]
379 assert node.implicit[4] == [three, four, one]
381 def test_add_ignore(self):
382 """Test adding files whose dependencies should be ignored.
384 node = SCons.Node.Node()
385 assert node.ignore == []
387 zero = SCons.Node.Node()
389 node.add_ignore(zero)
395 one = SCons.Node.Node()
396 two = SCons.Node.Node()
397 three = SCons.Node.Node()
398 four = SCons.Node.Node()
400 node.add_ignore([one])
401 assert node.ignore == [one]
402 node.add_ignore([two, three])
403 assert node.ignore == [one, two, three]
404 node.add_ignore([three, four, one])
405 assert node.ignore == [one, two, three, four]
407 assert zero.get_parents() == []
408 assert one.get_parents() == [node]
409 assert two.get_parents() == [node]
410 assert three.get_parents() == [node]
411 assert four.get_parents() == [node]
414 """Test Scanner functionality"""
418 node = SCons.Node.Node()
419 assert node.scanners == [], node.scanners
421 assert node.scanners == [ ds ], node.scanners
423 assert node.scanned[ds] == 1, node.scanned
425 def test_children(self):
426 """Test fetching the non-ignored "children" of a Node.
428 node = SCons.Node.Node()
429 one = SCons.Node.Node()
430 two = SCons.Node.Node()
431 three = SCons.Node.Node()
432 four = SCons.Node.Node()
433 five = SCons.Node.Node()
434 six = SCons.Node.Node()
436 node.add_source([one, two, three])
437 node.add_dependency([four, five, six])
438 node.add_ignore([two, five])
439 kids = node.children()
440 assert len(kids) == 4
442 assert not two in kids
445 assert not five in kids
448 def test_all_children(self):
449 """Test fetching all the "children" of a Node.
451 node = SCons.Node.Node()
452 one = SCons.Node.Node()
453 two = SCons.Node.Node()
454 three = SCons.Node.Node()
455 four = SCons.Node.Node()
456 five = SCons.Node.Node()
457 six = SCons.Node.Node()
459 node.add_source([one, two, three])
460 node.add_dependency([four, five, six])
461 node.add_ignore([two, five])
462 kids = node.all_children()
463 assert len(kids) == 6
471 def test_state(self):
472 """Test setting and getting the state of a node
474 node = SCons.Node.Node()
475 assert node.get_state() == None
476 node.set_state(SCons.Node.executing)
477 assert node.get_state() == SCons.Node.executing
478 assert SCons.Node.pending < SCons.Node.executing
479 assert SCons.Node.executing < SCons.Node.up_to_date
480 assert SCons.Node.up_to_date < SCons.Node.executed
481 assert SCons.Node.executed < SCons.Node.failed
483 def test_walker(self):
484 """Test walking a Node tree.
487 class MyNode(SCons.Node.Node):
488 def __init__(self, name):
489 SCons.Node.Node.__init__(self)
494 nw = SCons.Node.Walker(n1)
495 assert not nw.is_done()
496 assert nw.next().name == "n1"
498 assert nw.next() == None
502 n1.add_source([n2, n3])
504 nw = SCons.Node.Walker(n1)
505 assert nw.next().name == "n2"
506 assert nw.next().name == "n3"
507 assert nw.next().name == "n1"
508 assert nw.next() == None
514 n2.add_source([n4, n5])
515 n3.add_dependency([n6, n7])
517 nw = SCons.Node.Walker(n1)
518 assert nw.next().name == "n4"
519 assert nw.next().name == "n5"
520 assert nw.history.has_key(n2)
521 assert nw.next().name == "n2"
522 assert nw.next().name == "n6"
523 assert nw.next().name == "n7"
524 assert nw.history.has_key(n3)
525 assert nw.next().name == "n3"
526 assert nw.history.has_key(n1)
527 assert nw.next().name == "n1"
528 assert nw.next() == None
531 n8.add_dependency([n3])
532 n7.add_dependency([n8])
534 def cycle(node, stack):
535 global cycle_detected
538 global cycle_detected
540 nw = SCons.Node.Walker(n3, cycle_func = cycle)
542 assert n.name == "n6", n.name
544 assert n.name == "n8", n.name
545 assert cycle_detected
546 cycle_detected = None
548 assert n.name == "n7", n.name
550 assert nw.next() == None
552 def test_children_are_executed(self):
553 n1 = SCons.Node.Node()
554 n2 = SCons.Node.Node()
555 n3 = SCons.Node.Node()
556 n4 = SCons.Node.Node()
559 n3.add_source([n1, n2])
561 assert not n4.children_are_executed()
562 assert not n3.children_are_executed()
563 assert n2.children_are_executed()
564 assert n1.children_are_executed()
566 n1.set_state(SCons.Node.executed)
567 assert not n4.children_are_executed()
568 assert not n3.children_are_executed()
569 assert n2.children_are_executed()
570 assert n1.children_are_executed()
572 n2.set_state(SCons.Node.executed)
573 assert not n4.children_are_executed()
574 assert n3.children_are_executed()
575 assert n2.children_are_executed()
576 assert n1.children_are_executed()
578 n3.set_state(SCons.Node.executed)
579 assert n4.children_are_executed()
580 assert n3.children_are_executed()
581 assert n2.children_are_executed()
582 assert n1.children_are_executed()
584 def test_rescan(self):
585 """Test that built nodes are rescanned."""
589 class TestNode(SCons.Node.Node):
591 for scn in self.scanners:
592 if not self.scanned.has_key(scn):
595 self.add_implicit([ n ], scn)
596 self.scanned[scn] = 1
598 tn.builder_set(Builder())
599 tn.env_set(Environment())
603 map(lambda x: x.scan(), tn.depends)
604 assert tn.scanned[ds]
605 assert len(tn.implicit[ds]) == 1, tn.implicit
607 assert len(tn.implicit[ds]) == 2, tn.implicit
608 for dep in tn.implicit[ds]:
609 assert dep.scanned[ds] == 1
611 if __name__ == "__main__":
612 suite = unittest.makeSuite(NodeTestCase, 'test_')
613 if not unittest.TextTestRunner().run(suite).wasSuccessful():