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__"
45 def _actionAppend(a1, a2):
47 for curr_a in [a1, a2]:
48 if isinstance(curr_a, MyAction):
50 elif isinstance(curr_a, MyListAction):
51 all.extend(curr_a.list)
52 elif type(curr_a) == type([1,2]):
55 raise 'Cannot Combine Actions'
56 return MyListAction(all)
59 def __add__(self, other):
60 return _actionAppend(self, other)
62 def __radd__(self, other):
63 return _actionAppend(other, self)
65 class MyAction(MyActionBase):
69 def __call__(self, target, source, env, errfunc):
70 global built_it, built_target, built_source, built_args, built_order
75 built_order = built_order + 1
76 self.order = built_order
79 class MyListAction(MyActionBase):
80 def __init__(self, list):
82 def __call__(self, target, source, env, errfunc):
84 A(target, source, env, errfunc)
86 class MyNonGlobalAction(MyActionBase):
90 self.built_target = None
91 self.built_source = None
93 def __call__(self, target, source, env, errfunc):
94 # Okay, so not ENTIRELY non-global...
97 self.built_target = target
98 self.built_source = source
100 built_order = built_order + 1
101 self.order = built_order
105 def __init__(self, **kw):
107 self._dict.update(kw)
108 def __getitem__(self, key):
109 return self._dict[key]
110 def Dictionary(self, *args):
112 def Override(self, overrides):
113 d = self._dict.copy()
115 return apply(Environment, (), d)
116 def _update(self, dict):
117 self._dict.update(dict)
118 def get_calculator(self):
119 return SCons.Sig.default_calc
120 def get_scanner(self, scanner_key):
121 return self._dict['SCANNERS'][0]
124 def __init__(self, env=None, is_explicit=1):
125 if env is None: env = Environment()
128 self.action = MyAction()
129 self.source_factory = MyNode
130 self.is_explicit = is_explicit
131 def targets(self, t):
133 def get_actions(self):
135 def get_contents(self, target, source, env):
138 class NoneBuilder(Builder):
139 def execute(self, target, source, env):
140 Builder.execute(self, target, source, env)
143 class ListBuilder(Builder):
144 def __init__(self, *nodes):
145 Builder.__init__(self)
147 def execute(self, target, source, env):
148 if hasattr(self, 'status'):
152 target = self.nodes[0]
153 self.status = Builder.execute(self, target, source, env)
156 def execute(self, target, source, env):
160 def execute(self, target, source, env):
161 raise SCons.Errors.BuildError
163 class ExceptBuilder2:
164 def execute(self, target, source, env):
169 def __call__(self, node):
171 return node.found_includes
172 def select(self, node):
175 class MyNode(SCons.Node.Node):
176 """The base Node class contains a number of do-nothing methods that
177 we expect to be overridden by real, functional Node subclasses. So
178 simulate a real, functional Node subclass.
180 def __init__(self, name):
181 SCons.Node.Node.__init__(self)
183 self.found_includes = []
186 def get_found_includes(self, env, scanner, target):
190 def __init__(self, val):
193 def __init__(self, val):
195 def signature(self, args):
197 def collect(self, args):
198 return reduce(lambda x, y: x+y, args, self.val)
203 class NodeTestCase(unittest.TestCase):
205 def test_build(self):
206 """Test building a node
208 global built_it, built_order
210 # Make sure it doesn't blow up if no builder is set.
213 assert built_it == None
214 node.build(extra_kw_argument = 1)
215 assert built_it == None
218 node.builder_set(Builder())
219 node.env_set(Environment())
221 node.sources = ["yyy", "zzz"]
224 assert built_target == [node], built_target
225 assert built_source == ["yyy", "zzz"], built_source
229 node.builder_set(NoneBuilder())
230 node.env_set(Environment())
232 node.sources = ["rrr", "sss"]
233 node.builder.overrides = { "foo" : 1, "bar" : 2 }
236 assert built_target == [node], built_target
237 assert built_source == ["rrr", "sss"], built_source
238 assert built_args["foo"] == 1, built_args
239 assert built_args["bar"] == 2, built_args
243 lb = ListBuilder(fff, ggg)
251 fff.sources = ["hhh", "iii"]
252 ggg.sources = ["hhh", "iii"]
253 # [Charles C. 1/7/2002] Uhhh, why are there no asserts here?
254 # [SK, 15 May 2003] I dunno, let's add some...
258 assert built_target == [fff], built_target
259 assert built_source == ["hhh", "iii"], built_source
263 assert built_target == [ggg], built_target
264 assert built_source == ["hhh", "iii"], built_source
270 # NOTE: No env_set()! We should pull the environment from the builder.
271 b.env = Environment()
272 b.overrides = { "on" : 3, "off" : 4 }
276 assert built_target[0] == jjj, built_target[0]
277 assert built_source == [], built_source
278 assert built_args["on"] == 3, built_args
279 assert built_args["off"] == 4, built_args
284 node.builder_set(Builder())
285 node.env_set(Environment())
286 node.sources = ["yyy", "zzz"]
287 pre1 = MyNonGlobalAction()
288 pre2 = MyNonGlobalAction()
289 post1 = MyNonGlobalAction()
290 post2 = MyNonGlobalAction()
291 node.add_pre_action(pre1)
292 node.add_pre_action(pre2)
293 node.add_post_action(post1)
294 node.add_post_action(post2)
299 assert post1.built_it
300 assert post2.built_it
301 assert pre1.order == 1, pre1.order
302 assert pre2.order == 2, pre1.order
303 # The action of the builder itself is order 3...
304 assert post1.order == 4, pre1.order
305 assert post2.order == 5, pre1.order
307 for act in [ pre1, pre2, post1, post2 ]:
308 assert type(act.built_target[0]) == type(MyNode("bar")), type(act.built_target[0])
309 assert str(act.built_target[0]) == "xxx", str(act.built_target[0])
310 assert act.built_source == ["yyy", "zzz"], act.built_source
312 def test_get_executor(self):
313 """Test the reset_executor() method"""
314 n = SCons.Node.Node()
318 except AttributeError:
321 self.fail("did not catch expected AttributeError")
328 n = SCons.Node.Node()
329 n.builder_set(Builder())
331 assert x.env == 'env1', x.env
333 n = SCons.Node.Node()
334 n.builder_set(Builder())
337 assert x.env == 'env2', x.env
339 def test_set_executor(self):
340 """Test the reset_executor() method"""
341 n = SCons.Node.Node()
343 assert n.executor == 1, n.executor
345 def test_reset_executor(self):
346 """Test the reset_executor() method"""
347 n = SCons.Node.Node()
349 assert n.executor == 1, n.executor
351 assert not hasattr(n, 'executor'), "unexpected executor attribute"
353 def test_built(self):
354 """Test the built() method"""
355 class SubNode(SCons.Node.Node):
361 assert n.cleared, n.cleared
363 def test_retrieve_from_cache(self):
364 """Test the base retrieve_from_cache() method"""
365 n = SCons.Node.Node()
366 r = n.retrieve_from_cache()
369 def test_visited(self):
370 """Test the base visited() method
372 Just make sure it's there and we can call it.
374 n = SCons.Node.Node()
377 def test_depends_on(self):
378 """Test the depends_on() method
380 parent = SCons.Node.Node()
381 child = SCons.Node.Node()
382 parent.add_dependency([child])
383 assert parent.depends_on([child])
385 def test_builder_set(self):
386 """Test setting a Node's Builder
388 node = SCons.Node.Node()
391 assert node.builder == b
393 def test_has_builder(self):
394 """Test the has_builder() method
396 n1 = SCons.Node.Node()
397 assert n1.has_builder() == 0
398 n1.builder_set(Builder())
399 assert n1.has_builder() == 1
401 def test_has_explicit_builder(self):
402 """Test the has_explicit_builder() method
404 n1 = SCons.Node.Node()
405 assert not n1.has_explicit_builder()
406 n1.builder_set(Builder(is_explicit=1))
407 assert n1.has_explicit_builder()
408 n1.builder_set(Builder(is_explicit=None))
409 assert not n1.has_explicit_builder()
411 def test_get_builder(self):
412 """Test the get_builder() method"""
413 n1 = SCons.Node.Node()
416 b = n1.get_builder(777)
421 b = n1.get_builder(999)
424 def test_multiple_side_effect_has_builder(self):
425 """Test the multiple_side_effect_has_builder() method
427 n1 = SCons.Node.Node()
428 assert n1.multiple_side_effect_has_builder() == 0
429 n1.builder_set(Builder())
430 assert n1.multiple_side_effect_has_builder() == 1
432 def test_is_derived(self):
433 """Test the is_derived() method
435 n1 = SCons.Node.Node()
436 n2 = SCons.Node.Node()
437 n3 = SCons.Node.Node()
439 n2.builder_set(Builder())
442 assert n1.is_derived() == 0
443 assert n2.is_derived() == 1
444 assert n3.is_derived() == 1
446 def test_alter_targets(self):
447 """Test the alter_targets() method
449 n = SCons.Node.Node()
450 t, m = n.alter_targets()
454 def test_current(self):
455 """Test the default current() method
457 node = SCons.Node.Node()
458 assert node.current() is None
460 def test_children_are_up_to_date(self):
461 """Test the children_are_up_to_date() method used by subclasses
463 n1 = SCons.Node.Node()
464 n2 = SCons.Node.Node()
466 calc = Calculator(111)
469 assert n1.children_are_up_to_date(calc), "expected up to date"
470 n2.set_state(SCons.Node.executed)
471 assert not n1.children_are_up_to_date(calc), "expected not up to date"
472 n2.set_state(SCons.Node.up_to_date)
473 assert n1.children_are_up_to_date(calc), "expected up to date"
475 assert not n1.children_are_up_to_date(calc), "expected not up to date"
477 def test_env_set(self):
478 """Test setting a Node's Environment
480 node = SCons.Node.Node()
485 def test_get_actions(self):
486 """Test fetching a Node's action list
488 node = SCons.Node.Node()
489 node.builder_set(Builder())
490 a = node.builder.get_actions()
491 assert isinstance(a[0], MyAction), a[0]
493 def test_calc_bsig(self):
494 """Test generic build signature calculation
496 node = SCons.Node.Node()
497 result = node.calc_bsig(Calculator(222))
498 assert result == 222, result
499 result = node.calc_bsig(Calculator(333))
500 assert result == 222, result
502 def test_calc_csig(self):
503 """Test generic content signature calculation
505 node = SCons.Node.Node()
506 result = node.calc_csig(Calculator(444))
507 assert result == 444, result
508 result = node.calc_csig(Calculator(555))
509 assert result == 444, result
511 def test_gen_binfo(self):
512 """Test generating a build information structure
514 node = SCons.Node.Node()
515 binfo = node.gen_binfo(Calculator(666))
516 assert isinstance(binfo, SCons.Node.BuildInfo), binfo
517 assert hasattr(binfo, 'bsources')
518 assert hasattr(binfo, 'bsourcesigs')
519 assert hasattr(binfo, 'bdepends')
520 assert hasattr(binfo, 'bdependsigs')
521 assert hasattr(binfo, 'bimplicit')
522 assert hasattr(binfo, 'bimplicitsigs')
523 assert binfo.bsig == 666, binfo.bsig
525 def test_explain(self):
526 """Test explaining why a Node must be rebuilt
528 class testNode(SCons.Node.Node):
529 def __str__(self): return 'xyzzy'
531 node.exists = lambda: None
532 # Can't do this with new-style classes (python bug #1066490)
533 #node.__str__ = lambda: 'xyzzy'
534 result = node.explain()
535 assert result == "building `xyzzy' because it doesn't exist\n", result
537 class testNode2(SCons.Node.Node):
538 def __str__(self): return 'null_binfo'
540 result = node.explain()
541 assert result == None, result
547 node.get_stored_info = Null_BInfo
548 #see above: node.__str__ = lambda: 'null_binfo'
549 result = node.explain()
550 assert result == "Cannot explain why `null_binfo' is being rebuilt: No previous build information found\n", result
552 # XXX additional tests for the guts of the functionality some day
554 def test_del_binfo(self):
555 """Test deleting the build information from a Node
557 node = SCons.Node.Node()
560 assert not hasattr(node, 'binfo'), node
562 def test_store_info(self):
563 """Test calling the method to store build information
567 node = SCons.Node.Node()
568 node.store_info(Entry())
570 def test_get_stored_info(self):
571 """Test calling the method to fetch stored build information
573 node = SCons.Node.Node()
574 result = node.get_stored_info()
575 assert result is None, result
577 def test_set_always_build(self):
578 """Test setting a Node's always_build value
580 node = SCons.Node.Node()
581 node.set_always_build()
582 assert node.always_build
583 node.set_always_build(3)
584 assert node.always_build == 3
586 def test_set_precious(self):
587 """Test setting a Node's precious value
589 node = SCons.Node.Node()
593 assert node.precious == 7
595 def test_exists(self):
596 """Test evaluating whether a Node exists.
598 node = SCons.Node.Node()
602 def test_exists(self):
603 """Test evaluating whether a Node exists locally or in a repository.
605 node = SCons.Node.Node()
609 class MyNode(SCons.Node.Node):
617 def test_prepare(self):
618 """Test preparing a node to be built
620 node = SCons.Node.Node()
622 n1 = SCons.Node.Node()
623 n1.builder_set(Builder())
625 node.implicit_dict = {}
626 node._add_child(node.implicit, node.implicit_dict, [n1])
628 node.prepare() # should not throw an exception
630 n2 = SCons.Node.Node()
633 node.implicit_dict = {}
634 node._add_child(node.implicit, node.implicit_dict, [n2])
636 node.prepare() # should not throw an exception
638 n3 = SCons.Node.Node()
640 node.implicit_dict = {}
641 node._add_child(node.implicit, node.implicit_dict, [n3])
643 node.prepare() # should not throw an exception
645 class MyNode(SCons.Node.Node):
650 node.implicit_dict = {}
651 node._add_child(node.implicit, node.implicit_dict, [n4])
655 except SCons.Errors.StopError:
657 assert exc_caught, "did not catch expected StopError"
659 def test_add_dependency(self):
660 """Test adding dependencies to a Node's list.
662 node = SCons.Node.Node()
663 assert node.depends == []
665 zero = SCons.Node.Node()
667 one = SCons.Node.Node()
668 two = SCons.Node.Node()
669 three = SCons.Node.Node()
670 four = SCons.Node.Node()
671 five = SCons.Node.Node()
672 six = SCons.Node.Node()
674 node.add_dependency(zero)
675 assert node.depends == [zero]
676 node.add_dependency([one])
677 assert node.depends == [zero, one]
678 node.add_dependency([two, three])
679 assert node.depends == [zero, one, two, three]
680 node.add_dependency([three, four, one])
681 assert node.depends == [zero, one, two, three, four]
684 node.add_depends([[five, six]])
688 raise "did not catch expected exception"
689 assert node.depends == [zero, one, two, three, four]
692 def test_add_source(self):
693 """Test adding sources to a Node's list.
695 node = SCons.Node.Node()
696 assert node.sources == []
698 zero = SCons.Node.Node()
699 one = SCons.Node.Node()
700 two = SCons.Node.Node()
701 three = SCons.Node.Node()
702 four = SCons.Node.Node()
703 five = SCons.Node.Node()
704 six = SCons.Node.Node()
706 node.add_source(zero)
707 assert node.sources == [zero]
708 node.add_source([one])
709 assert node.sources == [zero, one]
710 node.add_source([two, three])
711 assert node.sources == [zero, one, two, three]
712 node.add_source([three, four, one])
713 assert node.sources == [zero, one, two, three, four]
716 node.add_source([[five, six]])
720 raise "did not catch expected exception"
721 assert node.sources == [zero, one, two, three, four]
723 def test_add_ignore(self):
724 """Test adding files whose dependencies should be ignored.
726 node = SCons.Node.Node()
727 assert node.ignore == []
729 zero = SCons.Node.Node()
730 one = SCons.Node.Node()
731 two = SCons.Node.Node()
732 three = SCons.Node.Node()
733 four = SCons.Node.Node()
734 five = SCons.Node.Node()
735 six = SCons.Node.Node()
737 node.add_ignore(zero)
738 assert node.ignore == [zero]
739 node.add_ignore([one])
740 assert node.ignore == [zero, one]
741 node.add_ignore([two, three])
742 assert node.ignore == [zero, one, two, three]
743 node.add_ignore([three, four, one])
744 assert node.ignore == [zero, one, two, three, four]
747 node.add_ignore([[five, six]])
751 raise "did not catch expected exception"
752 assert node.ignore == [zero, one, two, three, four]
754 def test_get_found_includes(self):
755 """Test the default get_found_includes() method
757 node = SCons.Node.Node()
758 target = SCons.Node.Node()
760 deps = node.get_found_includes(e, None, target)
761 assert deps == [], deps
763 def test_get_implicit_deps(self):
764 """Test get_implicit_deps()
767 target = MyNode("ttt")
770 # No scanner at all returns []
771 deps = node.get_implicit_deps(env, None, target)
772 assert deps == [], deps
776 node.found_includes = [d]
778 # Simple return of the found includes
779 deps = node.get_implicit_deps(env, s, target)
780 assert deps == [d], deps
782 # No "recursive" attribute on scanner doesn't recurse
784 d.found_includes = [e]
785 deps = node.get_implicit_deps(env, s, target)
786 assert deps == [d], map(str, deps)
788 # Explicit "recursive" attribute on scanner doesn't recurse
790 deps = node.get_implicit_deps(env, s, target)
791 assert deps == [d], map(str, deps)
793 # Explicit "recursive" attribute on scanner which does recurse
795 deps = node.get_implicit_deps(env, s, target)
796 assert deps == [d, e], map(str, deps)
798 # Recursive scanning eliminates duplicates
800 d.found_includes = [e, f]
801 e.found_includes = [f]
802 deps = node.get_implicit_deps(env, s, target)
803 assert deps == [d, e, f], map(str, deps)
805 def test_get_source_scanner(self):
806 """Test fetching the source scanner for a Node
808 target = SCons.Node.Node()
809 source = SCons.Node.Node()
810 s = target.get_source_scanner(source)
817 class Builder1(Builder):
818 def __call__(self, source):
819 r = SCons.Node.Node()
822 class Builder2(Builder1):
823 def __init__(self, scanner):
824 self.source_scanner = scanner
826 builder = Builder2(ts1)
828 targets = builder([source])
829 s = targets[0].get_source_scanner(source)
832 target.builder_set(Builder2(ts1))
833 target.builder.source_scanner = ts2
834 s = target.get_source_scanner(source)
837 builder = Builder1(env=Environment(SCANNERS = [ts3]))
839 targets = builder([source])
841 s = targets[0].get_source_scanner(source)
846 """Test Scanner functionality
849 node.builder = Builder()
850 node.env_set(Environment())
854 node.found_includes = [d]
856 node.builder.target_scanner = s
857 assert node.implicit is None
861 assert node.implicit == [d], node.implicit
863 # Check that scanning a node with some stored implicit
864 # dependencies resets internal attributes appropriately
865 # if the stored dependencies need recalculation.
866 class StoredNode(MyNode):
867 def get_stored_implicit(self):
868 return ['implicit1', 'implicit2']
871 def current(self, node, sig):
873 def bsig(self, node):
878 save_default_calc = SCons.Sig.default_calc
879 save_implicit_cache = SCons.Node.implicit_cache
880 save_implicit_deps_changed = SCons.Node.implicit_deps_changed
881 save_implicit_deps_unchanged = SCons.Node.implicit_deps_unchanged
882 SCons.Sig.default_calc = NotCurrent()
883 SCons.Node.implicit_cache = 1
884 SCons.Node.implicit_deps_changed = None
885 SCons.Node.implicit_deps_unchanged = None
887 sn = StoredNode("eee")
888 sn.builder_set(Builder())
889 sn.builder.target_scanner = s
893 assert sn.implicit == [], sn.implicit
894 assert sn.children() == [], sn.children()
897 SCons.Sig.default_calc = save_default_calc
898 SCons.Node.implicit_cache = save_implicit_cache
899 SCons.Node.implicit_deps_changed = save_implicit_deps_changed
900 SCons.Node.implicit_deps_unchanged = save_implicit_deps_unchanged
902 def test_scanner_key(self):
903 """Test that a scanner_key() method exists"""
904 assert SCons.Node.Node().scanner_key() == None
906 def test_children(self):
907 """Test fetching the non-ignored "children" of a Node.
909 node = SCons.Node.Node()
910 n1 = SCons.Node.Node()
911 n2 = SCons.Node.Node()
912 n3 = SCons.Node.Node()
913 n4 = SCons.Node.Node()
914 n5 = SCons.Node.Node()
915 n6 = SCons.Node.Node()
916 n7 = SCons.Node.Node()
917 n8 = SCons.Node.Node()
918 n9 = SCons.Node.Node()
919 n10 = SCons.Node.Node()
920 n11 = SCons.Node.Node()
921 n12 = SCons.Node.Node()
923 node.add_source([n1, n2, n3])
924 node.add_dependency([n4, n5, n6])
926 node.implicit_dict = {}
927 node._add_child(node.implicit, node.implicit_dict, [n7, n8, n9])
928 node._add_child(node.implicit, node.implicit_dict, [n10, n11, n12])
929 node.add_ignore([n2, n5, n8, n11])
931 kids = node.children()
932 for kid in [n1, n3, n4, n6, n7, n9, n10, n12]:
933 assert kid in kids, kid
934 for kid in [n2, n5, n8, n11]:
935 assert not kid in kids, kid
937 def test_all_children(self):
938 """Test fetching all the "children" of a Node.
940 node = SCons.Node.Node()
941 n1 = SCons.Node.Node()
942 n2 = SCons.Node.Node()
943 n3 = SCons.Node.Node()
944 n4 = SCons.Node.Node()
945 n5 = SCons.Node.Node()
946 n6 = SCons.Node.Node()
947 n7 = SCons.Node.Node()
948 n8 = SCons.Node.Node()
949 n9 = SCons.Node.Node()
950 n10 = SCons.Node.Node()
951 n11 = SCons.Node.Node()
952 n12 = SCons.Node.Node()
954 node.add_source([n1, n2, n3])
955 node.add_dependency([n4, n5, n6])
957 node.implicit_dict = {}
958 node._add_child(node.implicit, node.implicit_dict, [n7, n8, n9])
959 node._add_child(node.implicit, node.implicit_dict, [n10, n11, n12])
960 node.add_ignore([n2, n5, n8, n11])
962 kids = node.all_children()
963 for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12]:
964 assert kid in kids, kid
966 def test_state(self):
967 """Test setting and getting the state of a node
969 node = SCons.Node.Node()
970 assert node.get_state() == None
971 node.set_state(SCons.Node.executing)
972 assert node.get_state() == SCons.Node.executing
973 assert SCons.Node.pending < SCons.Node.executing
974 assert SCons.Node.executing < SCons.Node.up_to_date
975 assert SCons.Node.up_to_date < SCons.Node.executed
976 assert SCons.Node.executed < SCons.Node.failed
978 def test_walker(self):
979 """Test walking a Node tree.
984 nw = SCons.Node.Walker(n1)
985 assert not nw.is_done()
986 assert nw.next().name == "n1"
988 assert nw.next() == None
992 n1.add_source([n2, n3])
994 nw = SCons.Node.Walker(n1)
996 assert n.name == "n2", n.name
998 assert n.name == "n3", n.name
1000 assert n.name == "n1", n.name
1008 n2.add_source([n4, n5])
1009 n3.add_dependency([n6, n7])
1011 nw = SCons.Node.Walker(n1)
1012 assert nw.next().name == "n4"
1013 assert nw.next().name == "n5"
1014 assert nw.history.has_key(n2)
1015 assert nw.next().name == "n2"
1016 assert nw.next().name == "n6"
1017 assert nw.next().name == "n7"
1018 assert nw.history.has_key(n3)
1019 assert nw.next().name == "n3"
1020 assert nw.history.has_key(n1)
1021 assert nw.next().name == "n1"
1022 assert nw.next() == None
1025 n8.add_dependency([n3])
1026 n7.add_dependency([n8])
1028 def cycle(node, stack):
1029 global cycle_detected
1032 global cycle_detected
1034 nw = SCons.Node.Walker(n3, cycle_func = cycle)
1036 assert n.name == "n6", n.name
1038 assert n.name == "n8", n.name
1039 assert cycle_detected
1040 cycle_detected = None
1042 assert n.name == "n7", n.name
1044 assert nw.next() == None
1046 def test_abspath(self):
1047 """Test the get_abspath() method."""
1049 assert n.get_abspath() == str(n), n.get_abspath()
1051 def test_for_signature(self):
1052 """Test the for_signature() method."""
1054 assert n.for_signature() == str(n), n.get_abspath()
1056 def test_get_string(self):
1057 """Test the get_string() method."""
1058 class TestNode(MyNode):
1059 def __init__(self, name, sig):
1060 MyNode.__init__(self, name)
1063 def for_signature(self):
1066 n = TestNode("foo", "bar")
1067 assert n.get_string(0) == "foo", n.get_string(0)
1068 assert n.get_string(1) == "bar", n.get_string(1)
1070 def test_literal(self):
1071 """Test the is_literal() function."""
1073 assert n.is_literal()
1075 def test_Annotate(self):
1076 """Test using an interface-specific Annotate function."""
1077 def my_annotate(node, self=self):
1078 node.annotation = self.node_string
1080 save_Annotate = SCons.Node.Annotate
1081 SCons.Node.Annotate = my_annotate
1084 self.node_string = '#1'
1085 n = SCons.Node.Node()
1086 assert n.annotation == '#1', n.annotation
1088 self.node_string = '#2'
1089 n = SCons.Node.Node()
1090 assert n.annotation == '#2', n.annotation
1092 SCons.Node.Annotate = save_Annotate
1094 def test_clear(self):
1095 """Test clearing all cached state information."""
1096 n = SCons.Node.Node()
1100 n.includes = 'testincludes'
1101 n.found_include = {'testkey':'testvalue'}
1102 n.implicit = 'testimplicit'
1103 n.waiting_parents = ['foo', 'bar']
1107 assert not hasattr(n, 'binfo'), n.bsig
1108 assert n.includes is None, n.includes
1109 assert n.found_includes == {}, n.found_includes
1110 assert n.implicit is None, n.implicit
1111 assert n.waiting_parents == [], n.waiting_parents
1113 def test_get_subst_proxy(self):
1114 """Test the get_subst_proxy method."""
1117 assert n.get_subst_proxy() == n, n.get_subst_proxy()
1119 def test_new_binfo(self):
1120 """Test the new_binfo() method"""
1121 n = SCons.Node.Node()
1122 result = n.new_binfo()
1123 assert isinstance(result, SCons.Node.BuildInfo), result
1125 def test_get_suffix(self):
1126 """Test the base Node get_suffix() method"""
1127 n = SCons.Node.Node()
1131 def test_generate_build_dict(self):
1132 """Test the base Node generate_build_dict() method"""
1133 n = SCons.Node.Node()
1134 dict = n.generate_build_dict()
1135 assert dict == {}, dict
1137 def test_postprocess(self):
1138 """Test calling the base Node postprocess() method"""
1139 n = SCons.Node.Node()
1142 def test_add_to_waiting_parents(self):
1143 """Test the add_to_waiting_parents() method"""
1144 n1 = SCons.Node.Node()
1145 n2 = SCons.Node.Node()
1146 assert n1.waiting_parents == [], n1.waiting_parents
1147 n1.add_to_waiting_parents(n2)
1148 assert n1.waiting_parents == [n2], n1.waiting_parents
1150 def test_call_for_all_waiting_parents(self):
1151 """Test the call_for_all_waiting_parents() method"""
1152 n1 = SCons.Node.Node()
1153 n2 = SCons.Node.Node()
1154 n1.add_to_waiting_parents(n2)
1156 def func(node, result=result):
1158 n1.call_for_all_waiting_parents(func)
1159 assert result == [n1, n2], result
1161 class NodeListTestCase(unittest.TestCase):
1162 def test___str__(self):
1167 nl = SCons.Node.NodeList([n3, n2, n1])
1170 ul = UserList.UserList([2])
1174 # An older version of Python (*cough* 1.5.2 *cough*)
1175 # that doesn't allow UserList objects to extend lists.
1179 assert s == "['n3', 'n2', 'n1']", s
1182 r = re.sub('at (0x)?[0-9a-z]+', 'at 0x', r)
1183 # Don't care about ancestry: just leaf value of MyNode
1184 r = re.sub('<.*?\.MyNode', '<MyNode', r)
1185 # New-style classes report as "object"; classic classes report
1187 r = re.sub("object", "instance", r)
1188 l = string.join(["<MyNode instance at 0x>"]*3, ", ")
1189 assert r == '[%s]' % l, r
1193 if __name__ == "__main__":
1194 suite = unittest.TestSuite()
1195 tclasses = [ NodeTestCase,
1197 for tclass in tclasses:
1198 names = unittest.getTestCaseNames(tclass, 'test_')
1199 suite.addTests(map(tclass, names))
1200 if not unittest.TextTestRunner().run(suite).wasSuccessful():