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.
23 from __future__ import generators ### KEEP FOR COMPATIBILITY FIXERS
25 __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 isinstance(curr_a, list):
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, executor=None):
70 global built_it, built_target, built_source, built_args, built_order
72 target = executor.get_all_targets()
73 source = executor.get_all_sources()
78 built_order = built_order + 1
79 self.order = built_order
82 def get_implicit_deps(self, target, source, env):
86 def __init__(self, env=None, targets=[], sources=[]):
88 self.targets = targets
89 self.sources = sources
90 def get_build_env(self):
92 def get_build_scanner_path(self, scanner):
93 return 'executor would call %s' % scanner
96 def scan_targets(self, scanner):
99 d = scanner(self.targets)
100 for t in self.targets:
102 def scan_sources(self, scanner):
105 d = scanner(self.sources)
106 for t in self.targets:
109 class MyListAction(MyActionBase):
110 def __init__(self, list):
112 def __call__(self, target, source, env):
114 A(target, source, env)
117 def __init__(self, **kw):
119 self._dict.update(kw)
120 def __getitem__(self, key):
121 return self._dict[key]
122 def Dictionary(self, *args):
124 def Override(self, overrides):
125 d = self._dict.copy()
127 return Environment(**d)
128 def _update(self, dict):
129 self._dict.update(dict)
130 def get_factory(self, factory):
131 return factory or MyNode
132 def get_scanner(self, scanner_key):
133 return self._dict['SCANNERS'][0]
136 def __init__(self, env=None, is_explicit=1):
137 if env is None: env = Environment()
140 self.action = MyAction()
141 self.source_factory = MyNode
142 self.is_explicit = is_explicit
143 self.target_scanner = None
144 self.source_scanner = None
145 def targets(self, t):
147 def get_actions(self):
149 def get_contents(self, target, source, env):
152 class NoneBuilder(Builder):
153 def execute(self, target, source, env):
154 Builder.execute(self, target, source, env)
157 class ListBuilder(Builder):
158 def __init__(self, *nodes):
159 Builder.__init__(self)
161 def execute(self, target, source, env):
162 if hasattr(self, 'status'):
166 target = self.nodes[0]
167 self.status = Builder.execute(self, target, source, env)
170 def execute(self, target, source, env):
174 def execute(self, target, source, env):
175 raise SCons.Errors.BuildError
177 class ExceptBuilder2:
178 def execute(self, target, source, env):
183 def __call__(self, node):
185 return node.found_includes
186 def path(self, env, dir, target=None, source=None):
188 def select(self, node):
190 def recurse_nodes(self, nodes):
193 class MyNode(SCons.Node.Node):
194 """The base Node class contains a number of do-nothing methods that
195 we expect to be overridden by real, functional Node subclasses. So
196 simulate a real, functional Node subclass.
198 def __init__(self, name):
199 SCons.Node.Node.__init__(self)
201 self.found_includes = []
204 def get_found_includes(self, env, scanner, target):
208 def __init__(self, val):
211 def __init__(self, val):
213 def signature(self, args):
215 def collect(self, args):
216 return reduce(lambda x, y: x+y, args, self.val)
221 class NodeInfoBaseTestCase(unittest.TestCase):
223 def test_merge(self):
224 """Test merging NodeInfoBase attributes"""
225 ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node())
226 ni2 = SCons.Node.NodeInfoBase(SCons.Node.Node())
235 expect = {'a1':1, 'a2':222, 'a3':333, '_version_id':1}
236 assert ni1.__dict__ == expect, ni1.__dict__
238 def test_update(self):
239 """Test the update() method"""
240 ni = SCons.Node.NodeInfoBase(SCons.Node.Node())
241 ni.update(SCons.Node.Node())
243 def test_format(self):
244 """Test the NodeInfoBase.format() method"""
245 ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node())
251 assert f == ['1', 'x', 'y', 'z'], f
253 ni1.field_list = ['xxx', 'zzz', 'aaa']
256 assert f == ['x', 'z', 'None'], f
260 class BuildInfoBaseTestCase(unittest.TestCase):
262 def test___init__(self):
263 """Test BuildInfoBase initialization"""
264 n = SCons.Node.Node()
265 bi = SCons.Node.BuildInfoBase(n)
268 def test_merge(self):
269 """Test merging BuildInfoBase attributes"""
270 n1 = SCons.Node.Node()
271 bi1 = SCons.Node.BuildInfoBase(n1)
272 n2 = SCons.Node.Node()
273 bi2 = SCons.Node.BuildInfoBase(n2)
282 assert bi1.a1 == 1, bi1.a1
283 assert bi1.a2 == 222, bi1.a2
284 assert bi1.a3 == 333, bi1.a3
287 class NodeTestCase(unittest.TestCase):
289 def test_build(self):
290 """Test building a node
292 global built_it, built_order
294 # Make sure it doesn't blow up if no builder is set.
297 assert built_it is None
298 node.build(extra_kw_argument = 1)
299 assert built_it is None
302 node.builder_set(Builder())
303 node.env_set(Environment())
305 node.sources = ["yyy", "zzz"]
308 assert built_target == [node], built_target
309 assert built_source == ["yyy", "zzz"], built_source
313 node.builder_set(NoneBuilder())
314 node.env_set(Environment())
316 node.sources = ["rrr", "sss"]
317 node.builder.overrides = { "foo" : 1, "bar" : 2 }
320 assert built_target == [node], built_target
321 assert built_source == ["rrr", "sss"], built_source
322 assert built_args["foo"] == 1, built_args
323 assert built_args["bar"] == 2, built_args
327 lb = ListBuilder(fff, ggg)
335 fff.sources = ["hhh", "iii"]
336 ggg.sources = ["hhh", "iii"]
337 # [Charles C. 1/7/2002] Uhhh, why are there no asserts here?
338 # [SK, 15 May 2003] I dunno, let's add some...
342 assert built_target == [fff], built_target
343 assert built_source == ["hhh", "iii"], built_source
347 assert built_target == [ggg], built_target
348 assert built_source == ["hhh", "iii"], built_source
354 # NOTE: No env_set()! We should pull the environment from the builder.
355 b.env = Environment()
356 b.overrides = { "on" : 3, "off" : 4 }
360 assert built_target[0] == jjj, built_target[0]
361 assert built_source == [], built_source
362 assert built_args["on"] == 3, built_args
363 assert built_args["off"] == 4, built_args
365 def test_get_build_scanner_path(self):
366 """Test the get_build_scanner_path() method"""
367 n = SCons.Node.Node()
370 p = n.get_build_scanner_path('fake_scanner')
371 assert p == "executor would call fake_scanner", p
373 def test_get_executor(self):
374 """Test the get_executor() method"""
375 n = SCons.Node.Node()
379 except AttributeError:
382 self.fail("did not catch expected AttributeError")
389 n = SCons.Node.Node()
390 n.builder_set(Builder())
392 assert x.env == 'env1', x.env
394 n = SCons.Node.Node()
395 n.builder_set(Builder())
398 assert x.env == 'env2', x.env
400 def test_set_executor(self):
401 """Test the set_executor() method"""
402 n = SCons.Node.Node()
404 assert n.executor == 1, n.executor
406 def test_executor_cleanup(self):
407 """Test letting the executor cleanup its cache"""
408 n = SCons.Node.Node()
414 def test_reset_executor(self):
415 """Test the reset_executor() method"""
416 n = SCons.Node.Node()
418 assert n.executor == 1, n.executor
420 assert not hasattr(n, 'executor'), "unexpected executor attribute"
422 def test_built(self):
423 """Test the built() method"""
424 class SubNodeInfo(SCons.Node.NodeInfoBase):
425 def update(self, node):
427 class SubNode(SCons.Node.Node):
432 n.ninfo = SubNodeInfo(n)
434 assert n.cleared, n.cleared
435 assert n.ninfo.updated, n.ninfo.cleared
437 def test_push_to_cache(self):
438 """Test the base push_to_cache() method"""
439 n = SCons.Node.Node()
440 r = n.push_to_cache()
443 def test_retrieve_from_cache(self):
444 """Test the base retrieve_from_cache() method"""
445 n = SCons.Node.Node()
446 r = n.retrieve_from_cache()
449 def test_visited(self):
450 """Test the base visited() method
452 Just make sure it's there and we can call it.
454 n = SCons.Node.Node()
457 def test_builder_set(self):
458 """Test setting a Node's Builder
460 node = SCons.Node.Node()
463 assert node.builder == b
465 def test_has_builder(self):
466 """Test the has_builder() method
468 n1 = SCons.Node.Node()
469 assert n1.has_builder() == 0
470 n1.builder_set(Builder())
471 assert n1.has_builder() == 1
473 def test_has_explicit_builder(self):
474 """Test the has_explicit_builder() method
476 n1 = SCons.Node.Node()
477 assert not n1.has_explicit_builder()
479 assert n1.has_explicit_builder()
480 n1.set_explicit(None)
481 assert not n1.has_explicit_builder()
483 def test_get_builder(self):
484 """Test the get_builder() method"""
485 n1 = SCons.Node.Node()
488 b = n1.get_builder(777)
493 b = n1.get_builder(999)
496 def test_multiple_side_effect_has_builder(self):
497 """Test the multiple_side_effect_has_builder() method
499 n1 = SCons.Node.Node()
500 assert n1.multiple_side_effect_has_builder() == 0
501 n1.builder_set(Builder())
502 assert n1.multiple_side_effect_has_builder() == 1
504 def test_is_derived(self):
505 """Test the is_derived() method
507 n1 = SCons.Node.Node()
508 n2 = SCons.Node.Node()
509 n3 = SCons.Node.Node()
511 n2.builder_set(Builder())
514 assert n1.is_derived() == 0
515 assert n2.is_derived() == 1
516 assert n3.is_derived() == 1
518 def test_alter_targets(self):
519 """Test the alter_targets() method
521 n = SCons.Node.Node()
522 t, m = n.alter_targets()
526 def test_is_up_to_date(self):
527 """Test the default is_up_to_date() method
529 node = SCons.Node.Node()
530 assert node.is_up_to_date() is None
532 def test_children_are_up_to_date(self):
533 """Test the children_are_up_to_date() method used by subclasses
535 n1 = SCons.Node.Node()
536 n2 = SCons.Node.Node()
539 assert n1.children_are_up_to_date(), "expected up to date"
540 n2.set_state(SCons.Node.executed)
541 assert not n1.children_are_up_to_date(), "expected not up to date"
542 n2.set_state(SCons.Node.up_to_date)
543 assert n1.children_are_up_to_date(), "expected up to date"
545 assert not n1.children_are_up_to_date(), "expected not up to date"
547 def test_env_set(self):
548 """Test setting a Node's Environment
550 node = SCons.Node.Node()
555 def test_get_actions(self):
556 """Test fetching a Node's action list
558 node = SCons.Node.Node()
559 node.builder_set(Builder())
560 a = node.builder.get_actions()
561 assert isinstance(a[0], MyAction), a[0]
563 def test_get_csig(self):
564 """Test generic content signature calculation
566 node = SCons.Node.Node()
567 node.get_contents = lambda: 444
568 result = node.get_csig()
569 assert result == '550a141f12de6341fba65b0ad0433500', result
571 def test_get_cachedir_csig(self):
572 """Test content signature calculation for CacheDir
574 node = SCons.Node.Node()
575 node.get_contents = lambda: 555
576 result = node.get_cachedir_csig()
577 assert result == '15de21c670ae7c3f6f3f1f37029303c9', result
579 def test_get_binfo(self):
580 """Test fetching/creating a build information structure
582 node = SCons.Node.Node()
584 binfo = node.get_binfo()
585 assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo
587 node = SCons.Node.Node()
588 d = SCons.Node.Node()
589 d.get_ninfo().csig = 777
590 i = SCons.Node.Node()
591 i.get_ninfo().csig = 888
595 binfo = node.get_binfo()
596 assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo
597 assert hasattr(binfo, 'bsources')
598 assert hasattr(binfo, 'bsourcesigs')
599 assert binfo.bdepends == [d]
600 assert hasattr(binfo, 'bdependsigs')
601 assert binfo.bimplicit == [i]
602 assert hasattr(binfo, 'bimplicitsigs')
604 def test_explain(self):
605 """Test explaining why a Node must be rebuilt
607 class testNode(SCons.Node.Node):
608 def __str__(self): return 'xyzzy'
610 node.exists = lambda: None
611 # Can't do this with new-style classes (python bug #1066490)
612 #node.__str__ = lambda: 'xyzzy'
613 result = node.explain()
614 assert result == "building `xyzzy' because it doesn't exist\n", result
616 class testNode2(SCons.Node.Node):
617 def __str__(self): return 'null_binfo'
622 node.fs.Top = SCons.Node.Node()
623 result = node.explain()
624 assert result is None, result
627 class Null_SConsignEntry:
628 class Null_BuildInfo:
629 def prepare_dependencies(self):
631 binfo = Null_BuildInfo()
632 return Null_SConsignEntry()
634 node.get_stored_info = get_null_info
635 #see above: node.__str__ = lambda: 'null_binfo'
636 result = node.explain()
637 assert result == "Cannot explain why `null_binfo' is being rebuilt: No previous build information found\n", result
639 # XXX additional tests for the guts of the functionality some day
641 #def test_del_binfo(self):
642 # """Test deleting the build information from a Node
644 # node = SCons.Node.Node()
647 # assert not hasattr(node, 'binfo'), node
649 def test_store_info(self):
650 """Test calling the method to store build information
652 node = SCons.Node.Node()
655 def test_get_stored_info(self):
656 """Test calling the method to fetch stored build information
658 node = SCons.Node.Node()
659 result = node.get_stored_info()
660 assert result is None, result
662 def test_set_always_build(self):
663 """Test setting a Node's always_build value
665 node = SCons.Node.Node()
666 node.set_always_build()
667 assert node.always_build
668 node.set_always_build(3)
669 assert node.always_build == 3
671 def test_set_noclean(self):
672 """Test setting a Node's noclean value
674 node = SCons.Node.Node()
676 assert node.noclean == 1, node.noclean
678 assert node.noclean == 1, node.noclean
680 assert node.noclean == 0, node.noclean
681 node.set_noclean(None)
682 assert node.noclean == 0, node.noclean
684 def test_set_precious(self):
685 """Test setting a Node's precious value
687 node = SCons.Node.Node()
691 assert node.precious == 7
693 def test_exists(self):
694 """Test evaluating whether a Node exists.
696 node = SCons.Node.Node()
700 def test_exists(self):
701 """Test evaluating whether a Node exists locally or in a repository.
703 node = SCons.Node.Node()
707 class MyNode(SCons.Node.Node):
715 def test_prepare(self):
716 """Test preparing a node to be built
718 By extension, this also tests the missing() method.
720 node = SCons.Node.Node()
722 n1 = SCons.Node.Node()
723 n1.builder_set(Builder())
725 node.implicit_set = set()
726 node._add_child(node.implicit, node.implicit_set, [n1])
728 node.prepare() # should not throw an exception
730 n2 = SCons.Node.Node()
733 node.implicit_set = set()
734 node._add_child(node.implicit, node.implicit_set, [n2])
736 node.prepare() # should not throw an exception
738 n3 = SCons.Node.Node()
740 node.implicit_set = set()
741 node._add_child(node.implicit, node.implicit_set, [n3])
743 node.prepare() # should not throw an exception
745 class MyNode(SCons.Node.Node):
750 node.implicit_set = set()
751 node._add_child(node.implicit, node.implicit_set, [n4])
755 except SCons.Errors.StopError:
757 assert exc_caught, "did not catch expected StopError"
759 def test_add_dependency(self):
760 """Test adding dependencies to a Node's list.
762 node = SCons.Node.Node()
763 assert node.depends == []
765 zero = SCons.Node.Node()
767 one = SCons.Node.Node()
768 two = SCons.Node.Node()
769 three = SCons.Node.Node()
770 four = SCons.Node.Node()
771 five = SCons.Node.Node()
772 six = SCons.Node.Node()
774 node.add_dependency([zero])
775 assert node.depends == [zero]
776 node.add_dependency([one])
777 assert node.depends == [zero, one]
778 node.add_dependency([two, three])
779 assert node.depends == [zero, one, two, three]
780 node.add_dependency([three, four, one])
781 assert node.depends == [zero, one, two, three, four]
784 node.add_depends([[five, six]])
788 raise "did not catch expected exception"
789 assert node.depends == [zero, one, two, three, four]
792 def test_add_source(self):
793 """Test adding sources to a Node's list.
795 node = SCons.Node.Node()
796 assert node.sources == []
798 zero = SCons.Node.Node()
799 one = SCons.Node.Node()
800 two = SCons.Node.Node()
801 three = SCons.Node.Node()
802 four = SCons.Node.Node()
803 five = SCons.Node.Node()
804 six = SCons.Node.Node()
806 node.add_source([zero])
807 assert node.sources == [zero]
808 node.add_source([one])
809 assert node.sources == [zero, one]
810 node.add_source([two, three])
811 assert node.sources == [zero, one, two, three]
812 node.add_source([three, four, one])
813 assert node.sources == [zero, one, two, three, four]
816 node.add_source([[five, six]])
820 raise "did not catch expected exception"
821 assert node.sources == [zero, one, two, three, four], node.sources
823 def test_add_ignore(self):
824 """Test adding files whose dependencies should be ignored.
826 node = SCons.Node.Node()
827 assert node.ignore == []
829 zero = SCons.Node.Node()
830 one = SCons.Node.Node()
831 two = SCons.Node.Node()
832 three = SCons.Node.Node()
833 four = SCons.Node.Node()
834 five = SCons.Node.Node()
835 six = SCons.Node.Node()
837 node.add_ignore([zero])
838 assert node.ignore == [zero]
839 node.add_ignore([one])
840 assert node.ignore == [zero, one]
841 node.add_ignore([two, three])
842 assert node.ignore == [zero, one, two, three]
843 node.add_ignore([three, four, one])
844 assert node.ignore == [zero, one, two, three, four]
847 node.add_ignore([[five, six]])
851 raise "did not catch expected exception"
852 assert node.ignore == [zero, one, two, three, four]
854 def test_get_found_includes(self):
855 """Test the default get_found_includes() method
857 node = SCons.Node.Node()
858 target = SCons.Node.Node()
860 deps = node.get_found_includes(e, None, target)
861 assert deps == [], deps
863 def test_get_implicit_deps(self):
864 """Test get_implicit_deps()
867 target = MyNode("ttt")
870 # No scanner at all returns []
871 deps = node.get_implicit_deps(env, None, target)
872 assert deps == [], deps
877 node.found_includes = [d1, d2]
879 # Simple return of the found includes
880 deps = node.get_implicit_deps(env, s, target)
881 assert deps == [d1, d2], deps
883 # By default, our fake scanner recurses
887 d1.found_includes = [e, f]
888 d2.found_includes = [e, f]
889 f.found_includes = [g]
890 deps = node.get_implicit_deps(env, s, target)
891 assert deps == [d1, d2, e, f, g], list(map(str, deps))
893 # Recursive scanning eliminates duplicates
894 e.found_includes = [f]
895 deps = node.get_implicit_deps(env, s, target)
896 assert deps == [d1, d2, e, f, g], list(map(str, deps))
898 # Scanner method can select specific nodes to recurse
900 return [n for n in nodes if str(n)[0] != 'f']
901 s.recurse_nodes = no_fff
902 deps = node.get_implicit_deps(env, s, target)
903 assert deps == [d1, d2, e, f], list(map(str, deps))
905 # Scanner method can short-circuit recursing entirely
906 s.recurse_nodes = lambda nodes: []
907 deps = node.get_implicit_deps(env, s, target)
908 assert deps == [d1, d2], list(map(str, deps))
910 def test_get_env_scanner(self):
911 """Test fetching the environment scanner for a Node
913 node = SCons.Node.Node()
915 env = Environment(SCANNERS = [scanner])
916 s = node.get_env_scanner(env)
917 assert s == scanner, s
918 s = node.get_env_scanner(env, {'X':1})
919 assert s == scanner, s
921 def test_get_target_scanner(self):
922 """Test fetching the target scanner for a Node
927 n = SCons.Node.Node()
929 x = n.get_target_scanner()
932 def test_get_source_scanner(self):
933 """Test fetching the source scanner for a Node
935 target = SCons.Node.Node()
936 source = SCons.Node.Node()
937 s = target.get_source_scanner(source)
938 assert isinstance(s, SCons.Util.Null), s
944 class Builder1(Builder):
945 def __call__(self, source):
946 r = SCons.Node.Node()
949 class Builder2(Builder1):
950 def __init__(self, scanner):
951 self.source_scanner = scanner
953 builder = Builder2(ts1)
955 targets = builder([source])
956 s = targets[0].get_source_scanner(source)
959 target.builder_set(Builder2(ts1))
960 target.builder.source_scanner = ts2
961 s = target.get_source_scanner(source)
964 builder = Builder1(env=Environment(SCANNERS = [ts3]))
966 targets = builder([source])
968 s = targets[0].get_source_scanner(source)
973 """Test Scanner functionality
977 node.builder = Builder()
979 x = MyExecutor(env, [node])
983 node.found_includes = [d]
985 node.builder.target_scanner = s
986 assert node.implicit is None
990 assert node.implicit == [d], node.implicit
992 # Check that scanning a node with some stored implicit
993 # dependencies resets internal attributes appropriately
994 # if the stored dependencies need recalculation.
995 class StoredNode(MyNode):
996 def get_stored_implicit(self):
997 return [MyNode('implicit1'), MyNode('implicit2')]
999 save_implicit_cache = SCons.Node.implicit_cache
1000 save_implicit_deps_changed = SCons.Node.implicit_deps_changed
1001 save_implicit_deps_unchanged = SCons.Node.implicit_deps_unchanged
1002 SCons.Node.implicit_cache = 1
1003 SCons.Node.implicit_deps_changed = None
1004 SCons.Node.implicit_deps_unchanged = None
1006 sn = StoredNode("eee")
1007 sn.builder_set(Builder())
1008 sn.builder.target_scanner = s
1012 assert sn.implicit == [], sn.implicit
1013 assert sn.children() == [], sn.children()
1016 SCons.Node.implicit_cache = save_implicit_cache
1017 SCons.Node.implicit_deps_changed = save_implicit_deps_changed
1018 SCons.Node.implicit_deps_unchanged = save_implicit_deps_unchanged
1020 def test_scanner_key(self):
1021 """Test that a scanner_key() method exists"""
1022 assert SCons.Node.Node().scanner_key() is None
1024 def test_children(self):
1025 """Test fetching the non-ignored "children" of a Node.
1027 node = SCons.Node.Node()
1028 n1 = SCons.Node.Node()
1029 n2 = SCons.Node.Node()
1030 n3 = SCons.Node.Node()
1031 n4 = SCons.Node.Node()
1032 n5 = SCons.Node.Node()
1033 n6 = SCons.Node.Node()
1034 n7 = SCons.Node.Node()
1035 n8 = SCons.Node.Node()
1036 n9 = SCons.Node.Node()
1037 n10 = SCons.Node.Node()
1038 n11 = SCons.Node.Node()
1039 n12 = SCons.Node.Node()
1041 node.add_source([n1, n2, n3])
1042 node.add_dependency([n4, n5, n6])
1044 node.implicit_set = set()
1045 node._add_child(node.implicit, node.implicit_set, [n7, n8, n9])
1046 node._add_child(node.implicit, node.implicit_set, [n10, n11, n12])
1047 node.add_ignore([n2, n5, n8, n11])
1049 kids = node.children()
1050 for kid in [n1, n3, n4, n6, n7, n9, n10, n12]:
1051 assert kid in kids, kid
1052 for kid in [n2, n5, n8, n11]:
1053 assert not kid in kids, kid
1055 def test_all_children(self):
1056 """Test fetching all the "children" of a Node.
1058 node = SCons.Node.Node()
1059 n1 = SCons.Node.Node()
1060 n2 = SCons.Node.Node()
1061 n3 = SCons.Node.Node()
1062 n4 = SCons.Node.Node()
1063 n5 = SCons.Node.Node()
1064 n6 = SCons.Node.Node()
1065 n7 = SCons.Node.Node()
1066 n8 = SCons.Node.Node()
1067 n9 = SCons.Node.Node()
1068 n10 = SCons.Node.Node()
1069 n11 = SCons.Node.Node()
1070 n12 = SCons.Node.Node()
1072 node.add_source([n1, n2, n3])
1073 node.add_dependency([n4, n5, n6])
1075 node.implicit_set = set()
1076 node._add_child(node.implicit, node.implicit_set, [n7, n8, n9])
1077 node._add_child(node.implicit, node.implicit_set, [n10, n11, n12])
1078 node.add_ignore([n2, n5, n8, n11])
1080 kids = node.all_children()
1081 for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12]:
1082 assert kid in kids, kid
1084 def test_state(self):
1085 """Test setting and getting the state of a node
1087 node = SCons.Node.Node()
1088 assert node.get_state() == SCons.Node.no_state
1089 node.set_state(SCons.Node.executing)
1090 assert node.get_state() == SCons.Node.executing
1091 assert SCons.Node.pending < SCons.Node.executing
1092 assert SCons.Node.executing < SCons.Node.up_to_date
1093 assert SCons.Node.up_to_date < SCons.Node.executed
1094 assert SCons.Node.executed < SCons.Node.failed
1096 def test_walker(self):
1097 """Test walking a Node tree.
1102 nw = SCons.Node.Walker(n1)
1103 assert not nw.is_done()
1104 assert nw.next().name == "n1"
1106 assert nw.next() is None
1110 n1.add_source([n2, n3])
1112 nw = SCons.Node.Walker(n1)
1114 assert n.name == "n2", n.name
1116 assert n.name == "n3", n.name
1118 assert n.name == "n1", n.name
1126 n2.add_source([n4, n5])
1127 n3.add_dependency([n6, n7])
1129 nw = SCons.Node.Walker(n1)
1130 assert nw.next().name == "n4"
1131 assert nw.next().name == "n5"
1132 assert n2 in nw.history
1133 assert nw.next().name == "n2"
1134 assert nw.next().name == "n6"
1135 assert nw.next().name == "n7"
1136 assert n3 in nw.history
1137 assert nw.next().name == "n3"
1138 assert n1 in nw.history
1139 assert nw.next().name == "n1"
1140 assert nw.next() is None
1143 n8.add_dependency([n3])
1144 n7.add_dependency([n8])
1146 def cycle(node, stack):
1147 global cycle_detected
1150 global cycle_detected
1152 nw = SCons.Node.Walker(n3, cycle_func = cycle)
1154 assert n.name == "n6", n.name
1156 assert n.name == "n8", n.name
1157 assert cycle_detected
1158 cycle_detected = None
1160 assert n.name == "n7", n.name
1162 assert nw.next() is None
1164 def test_abspath(self):
1165 """Test the get_abspath() method."""
1167 assert n.get_abspath() == str(n), n.get_abspath()
1169 def test_for_signature(self):
1170 """Test the for_signature() method."""
1172 assert n.for_signature() == str(n), n.get_abspath()
1174 def test_get_string(self):
1175 """Test the get_string() method."""
1176 class TestNode(MyNode):
1177 def __init__(self, name, sig):
1178 MyNode.__init__(self, name)
1181 def for_signature(self):
1184 n = TestNode("foo", "bar")
1185 assert n.get_string(0) == "foo", n.get_string(0)
1186 assert n.get_string(1) == "bar", n.get_string(1)
1188 def test_literal(self):
1189 """Test the is_literal() function."""
1191 assert n.is_literal()
1193 def test_Annotate(self):
1194 """Test using an interface-specific Annotate function."""
1195 def my_annotate(node, self=self):
1196 node.annotation = self.node_string
1198 save_Annotate = SCons.Node.Annotate
1199 SCons.Node.Annotate = my_annotate
1202 self.node_string = '#1'
1203 n = SCons.Node.Node()
1204 assert n.annotation == '#1', n.annotation
1206 self.node_string = '#2'
1207 n = SCons.Node.Node()
1208 assert n.annotation == '#2', n.annotation
1210 SCons.Node.Annotate = save_Annotate
1212 def test_clear(self):
1213 """Test clearing all cached state information."""
1214 n = SCons.Node.Node()
1218 n.includes = 'testincludes'
1219 n.found_include = {'testkey':'testvalue'}
1220 n.implicit = 'testimplicit'
1227 assert n.includes is None, n.includes
1230 def test_get_subst_proxy(self):
1231 """Test the get_subst_proxy method."""
1234 assert n.get_subst_proxy() == n, n.get_subst_proxy()
1236 def test_new_binfo(self):
1237 """Test the new_binfo() method"""
1238 n = SCons.Node.Node()
1239 result = n.new_binfo()
1240 assert isinstance(result, SCons.Node.BuildInfoBase), result
1242 def test_get_suffix(self):
1243 """Test the base Node get_suffix() method"""
1244 n = SCons.Node.Node()
1248 def test_postprocess(self):
1249 """Test calling the base Node postprocess() method"""
1250 n = SCons.Node.Node()
1251 n.waiting_parents = set( ['foo','bar'] )
1254 assert n.waiting_parents == set(), n.waiting_parents
1256 def test_add_to_waiting_parents(self):
1257 """Test the add_to_waiting_parents() method"""
1258 n1 = SCons.Node.Node()
1259 n2 = SCons.Node.Node()
1260 assert n1.waiting_parents == set(), n1.waiting_parents
1261 r = n1.add_to_waiting_parents(n2)
1263 assert n1.waiting_parents == set((n2,)), n1.waiting_parents
1264 r = n1.add_to_waiting_parents(n2)
1268 class NodeListTestCase(unittest.TestCase):
1269 def test___str__(self):
1274 nl = SCons.Node.NodeList([n3, n2, n1])
1277 ul = UserList.UserList([2])
1281 # An older version of Python (*cough* 1.5.2 *cough*)
1282 # that doesn't allow UserList objects to extend lists.
1286 assert s == "['n3', 'n2', 'n1']", s
1289 r = re.sub('at (0[xX])?[0-9a-fA-F]+', 'at 0x', r)
1290 # Don't care about ancestry: just leaf value of MyNode
1291 r = re.sub('<.*?\.MyNode', '<MyNode', r)
1292 # New-style classes report as "object"; classic classes report
1294 r = re.sub("object", "instance", r)
1295 l = ", ".join(["<MyNode instance at 0x>"]*3)
1296 assert r == '[%s]' % l, r
1300 if __name__ == "__main__":
1301 suite = unittest.TestSuite()
1302 tclasses = [ BuildInfoBaseTestCase,
1303 NodeInfoBaseTestCase,
1306 for tclass in tclasses:
1307 names = unittest.getTestCaseNames(tclass, 'test_')
1308 suite.addTests(list(map(tclass, names)))
1309 if not unittest.TextTestRunner().run(suite).wasSuccessful():
1314 # indent-tabs-mode:nil
1316 # vim: set expandtab tabstop=4 shiftwidth=4: