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.scanner == None, node.scanner
421 assert node.scanner == ds, node.scanner
423 assert node.scanned[ds] == 1, node.scanned
425 def test_src_scanner_set(self):
426 """Test setting source-file Scanners"""
431 node = SCons.Node.Node()
432 assert node.src_scanners == {}, node.src_scanners
433 node.src_scanner_set('a', ds1)
434 assert node.src_scanners['a'] == ds1, node.src_scanners
435 node.src_scanner_set('b', ds2)
436 assert node.src_scanners['b'] == ds2, node.src_scanners
438 def test_src_scanner_set(self):
439 """Test setting source-file Scanners"""
444 node = SCons.Node.Node()
445 node.src_scanner_set('a', ds1)
446 node.src_scanner_set('b', ds2)
447 s = node.src_scanner_get(None)
449 s = node.src_scanner_get('a')
451 s = node.src_scanner_get('b')
453 s = node.src_scanner_get('c')
456 def test_scanner_key(self):
457 """Test that a scanner_key() method exists"""
458 assert SCons.Node.Node().scanner_key() == None
460 def test_children(self):
461 """Test fetching the non-ignored "children" of a Node.
463 node = SCons.Node.Node()
464 n1 = SCons.Node.Node()
465 n2 = SCons.Node.Node()
466 n3 = SCons.Node.Node()
467 n4 = SCons.Node.Node()
468 n5 = SCons.Node.Node()
469 n6 = SCons.Node.Node()
470 n7 = SCons.Node.Node()
471 n8 = SCons.Node.Node()
472 n9 = SCons.Node.Node()
473 n10 = SCons.Node.Node()
474 n11 = SCons.Node.Node()
475 n12 = SCons.Node.Node()
477 node.add_source([n1, n2, n3])
478 node.add_dependency([n4, n5, n6])
479 node.add_implicit([n7, n8, n9], 'key1')
480 node.add_implicit([n10, n11, n12], 'key2')
481 node.add_ignore([n2, n5, n8, n11])
483 kids = node.children(None)
484 for kid in [n1, n3, n4, n6, n7, n9, n10, n12]:
485 assert kid in kids, kid
486 for kid in [n2, n5, n8, n11]:
487 assert not kid in kids, kid
489 kids = node.children('key1')
490 for kid in [n1, n3, n4, n6, n7, n9]:
491 assert kid in kids, kid
492 for kid in [n2, n5, n8, n10, n11, n12]:
493 assert not kid in kids, kid
495 kids = node.children('key2')
496 for kid in [n1, n3, n4, n6, n10, n12]:
497 assert kid in kids, kid
498 for kid in [n2, n5, n7, n8, n9, n11]:
499 assert not kid in kids, kid
501 def test_all_children(self):
502 """Test fetching all the "children" of a Node.
504 node = SCons.Node.Node()
505 n1 = SCons.Node.Node()
506 n2 = SCons.Node.Node()
507 n3 = SCons.Node.Node()
508 n4 = SCons.Node.Node()
509 n5 = SCons.Node.Node()
510 n6 = SCons.Node.Node()
511 n7 = SCons.Node.Node()
512 n8 = SCons.Node.Node()
513 n9 = SCons.Node.Node()
514 n10 = SCons.Node.Node()
515 n11 = SCons.Node.Node()
516 n12 = SCons.Node.Node()
518 node.add_source([n1, n2, n3])
519 node.add_dependency([n4, n5, n6])
520 node.add_implicit([n7, n8, n9], 'key1')
521 node.add_implicit([n10, n11, n12], 'key2')
522 node.add_ignore([n2, n5, n8, n11])
524 kids = node.all_children(None)
525 for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12]:
528 kids = node.all_children('key1')
529 for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9]:
531 for kid in [n10, n11, n12]:
532 assert not kid in kids
534 kids = node.all_children('key2')
535 for kid in [n1, n2, n3, n4, n5, n6, n10, n11, n12]:
537 for kid in [n7, n8, n9]:
538 assert not kid in kids
540 def test_state(self):
541 """Test setting and getting the state of a node
543 node = SCons.Node.Node()
544 assert node.get_state() == None
545 node.set_state(SCons.Node.executing)
546 assert node.get_state() == SCons.Node.executing
547 assert SCons.Node.pending < SCons.Node.executing
548 assert SCons.Node.executing < SCons.Node.up_to_date
549 assert SCons.Node.up_to_date < SCons.Node.executed
550 assert SCons.Node.executed < SCons.Node.failed
552 def test_walker(self):
553 """Test walking a Node tree.
556 class MyNode(SCons.Node.Node):
557 def __init__(self, name):
558 SCons.Node.Node.__init__(self)
563 nw = SCons.Node.Walker(n1)
564 assert not nw.is_done()
565 assert nw.next().name == "n1"
567 assert nw.next() == None
571 n1.add_source([n2, n3])
573 nw = SCons.Node.Walker(n1)
574 assert nw.next().name == "n2"
575 assert nw.next().name == "n3"
576 assert nw.next().name == "n1"
577 assert nw.next() == None
583 n2.add_source([n4, n5])
584 n3.add_dependency([n6, n7])
586 nw = SCons.Node.Walker(n1)
587 assert nw.next().name == "n4"
588 assert nw.next().name == "n5"
589 assert nw.history.has_key(n2)
590 assert nw.next().name == "n2"
591 assert nw.next().name == "n6"
592 assert nw.next().name == "n7"
593 assert nw.history.has_key(n3)
594 assert nw.next().name == "n3"
595 assert nw.history.has_key(n1)
596 assert nw.next().name == "n1"
597 assert nw.next() == None
600 n8.add_dependency([n3])
601 n7.add_dependency([n8])
603 def cycle(node, stack):
604 global cycle_detected
607 global cycle_detected
609 nw = SCons.Node.Walker(n3, cycle_func = cycle)
611 assert n.name == "n6", n.name
613 assert n.name == "n8", n.name
614 assert cycle_detected
615 cycle_detected = None
617 assert n.name == "n7", n.name
619 assert nw.next() == None
621 def test_children_are_executed(self):
622 n1 = SCons.Node.Node()
623 n2 = SCons.Node.Node()
624 n3 = SCons.Node.Node()
625 n4 = SCons.Node.Node()
628 n3.add_source([n1, n2])
630 assert not n4.children_are_executed(None)
631 assert not n3.children_are_executed(None)
632 assert n2.children_are_executed(None)
633 assert n1.children_are_executed(None)
635 n1.set_state(SCons.Node.executed)
636 assert not n4.children_are_executed(None)
637 assert not n3.children_are_executed(None)
638 assert n2.children_are_executed(None)
639 assert n1.children_are_executed(None)
641 n2.set_state(SCons.Node.executed)
642 assert not n4.children_are_executed(None)
643 assert n3.children_are_executed(None)
644 assert n2.children_are_executed(None)
645 assert n1.children_are_executed(None)
647 n3.set_state(SCons.Node.executed)
648 assert n4.children_are_executed(None)
649 assert n3.children_are_executed(None)
650 assert n2.children_are_executed(None)
651 assert n1.children_are_executed(None)
653 def test_rescan(self):
654 """Test that built node implicit dependencies are cleared
659 class TestNode(SCons.Node.Node):
660 def scan(self, scanner):
661 if not self.scanned.has_key(scanner):
663 n.scanner_set(scanner)
664 self.add_implicit([ n ], scanner)
665 self.scanned[scanner] = 1
667 tn.builder_set(Builder())
668 tn.env_set(Environment())
671 map(lambda x: x.scan(), tn.depends)
672 assert tn.scanned[ds]
673 assert len(tn.implicit[ds]) == 1, tn.implicit
675 assert tn.scanned[ds]
676 assert len(tn.implicit[ds]) == 1, tn.implicit
678 assert not tn.scanned.has_key(ds)
679 assert len(tn.implicit[ds]) == 1, tn.implicit
681 assert tn.scanned[ds]
682 assert len(tn.implicit[ds]) == 2, tn.implicit
684 if __name__ == "__main__":
685 suite = unittest.makeSuite(NodeTestCase, 'test_')
686 if not unittest.TextTestRunner().run(suite).wasSuccessful():