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__"
47 def _actionAppend(a1, a2):
49 for curr_a in [a1, a2]:
50 if isinstance(curr_a, MyAction):
52 elif isinstance(curr_a, MyListAction):
53 all.extend(curr_a.list)
54 elif isinstance(curr_a, list):
57 raise 'Cannot Combine Actions'
58 return MyListAction(all)
61 def __add__(self, other):
62 return _actionAppend(self, other)
64 def __radd__(self, other):
65 return _actionAppend(other, self)
67 class MyAction(MyActionBase):
71 def __call__(self, target, source, env, executor=None):
72 global built_it, built_target, built_source, built_args, built_order
74 target = executor.get_all_targets()
75 source = executor.get_all_sources()
80 built_order = built_order + 1
81 self.order = built_order
84 def get_implicit_deps(self, target, source, env):
88 def __init__(self, env=None, targets=[], sources=[]):
90 self.targets = targets
91 self.sources = sources
92 def get_build_env(self):
94 def get_build_scanner_path(self, scanner):
95 return 'executor would call %s' % scanner
98 def scan_targets(self, scanner):
101 d = scanner(self.targets)
102 for t in self.targets:
104 def scan_sources(self, scanner):
107 d = scanner(self.sources)
108 for t in self.targets:
111 class MyListAction(MyActionBase):
112 def __init__(self, list):
114 def __call__(self, target, source, env):
116 A(target, source, env)
119 def __init__(self, **kw):
121 self._dict.update(kw)
122 def __getitem__(self, key):
123 return self._dict[key]
124 def Dictionary(self, *args):
126 def Override(self, overrides):
127 d = self._dict.copy()
129 return Environment(**d)
130 def _update(self, dict):
131 self._dict.update(dict)
132 def get_factory(self, factory):
133 return factory or MyNode
134 def get_scanner(self, scanner_key):
135 return self._dict['SCANNERS'][0]
138 def __init__(self, env=None, is_explicit=1):
139 if env is None: env = Environment()
142 self.action = MyAction()
143 self.source_factory = MyNode
144 self.is_explicit = is_explicit
145 self.target_scanner = None
146 self.source_scanner = None
147 def targets(self, t):
149 def get_actions(self):
151 def get_contents(self, target, source, env):
154 class NoneBuilder(Builder):
155 def execute(self, target, source, env):
156 Builder.execute(self, target, source, env)
159 class ListBuilder(Builder):
160 def __init__(self, *nodes):
161 Builder.__init__(self)
163 def execute(self, target, source, env):
164 if hasattr(self, 'status'):
168 target = self.nodes[0]
169 self.status = Builder.execute(self, target, source, env)
172 def execute(self, target, source, env):
176 def execute(self, target, source, env):
177 raise SCons.Errors.BuildError
179 class ExceptBuilder2:
180 def execute(self, target, source, env):
185 def __call__(self, node):
187 return node.found_includes
188 def path(self, env, dir, target=None, source=None):
190 def select(self, node):
192 def recurse_nodes(self, nodes):
195 class MyNode(SCons.Node.Node):
196 """The base Node class contains a number of do-nothing methods that
197 we expect to be overridden by real, functional Node subclasses. So
198 simulate a real, functional Node subclass.
200 def __init__(self, name):
201 SCons.Node.Node.__init__(self)
203 self.found_includes = []
206 def get_found_includes(self, env, scanner, target):
210 def __init__(self, val):
213 def __init__(self, val):
215 def signature(self, args):
217 def collect(self, args):
218 return reduce(lambda x, y: x+y, args, self.val)
223 class NodeInfoBaseTestCase(unittest.TestCase):
225 def test_merge(self):
226 """Test merging NodeInfoBase attributes"""
227 ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node())
228 ni2 = SCons.Node.NodeInfoBase(SCons.Node.Node())
237 expect = {'a1':1, 'a2':222, 'a3':333, '_version_id':1}
238 assert ni1.__dict__ == expect, ni1.__dict__
240 def test_update(self):
241 """Test the update() method"""
242 ni = SCons.Node.NodeInfoBase(SCons.Node.Node())
243 ni.update(SCons.Node.Node())
245 def test_format(self):
246 """Test the NodeInfoBase.format() method"""
247 ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node())
253 assert f == ['1', 'x', 'y', 'z'], f
255 ni1.field_list = ['xxx', 'zzz', 'aaa']
258 assert f == ['x', 'z', 'None'], f
262 class BuildInfoBaseTestCase(unittest.TestCase):
264 def test___init__(self):
265 """Test BuildInfoBase initialization"""
266 n = SCons.Node.Node()
267 bi = SCons.Node.BuildInfoBase(n)
270 def test_merge(self):
271 """Test merging BuildInfoBase attributes"""
272 n1 = SCons.Node.Node()
273 bi1 = SCons.Node.BuildInfoBase(n1)
274 n2 = SCons.Node.Node()
275 bi2 = SCons.Node.BuildInfoBase(n2)
284 assert bi1.a1 == 1, bi1.a1
285 assert bi1.a2 == 222, bi1.a2
286 assert bi1.a3 == 333, bi1.a3
289 class NodeTestCase(unittest.TestCase):
291 def test_build(self):
292 """Test building a node
294 global built_it, built_order
296 # Make sure it doesn't blow up if no builder is set.
299 assert built_it is None
300 node.build(extra_kw_argument = 1)
301 assert built_it is None
304 node.builder_set(Builder())
305 node.env_set(Environment())
307 node.sources = ["yyy", "zzz"]
310 assert built_target == [node], built_target
311 assert built_source == ["yyy", "zzz"], built_source
315 node.builder_set(NoneBuilder())
316 node.env_set(Environment())
318 node.sources = ["rrr", "sss"]
319 node.builder.overrides = { "foo" : 1, "bar" : 2 }
322 assert built_target == [node], built_target
323 assert built_source == ["rrr", "sss"], built_source
324 assert built_args["foo"] == 1, built_args
325 assert built_args["bar"] == 2, built_args
329 lb = ListBuilder(fff, ggg)
337 fff.sources = ["hhh", "iii"]
338 ggg.sources = ["hhh", "iii"]
339 # [Charles C. 1/7/2002] Uhhh, why are there no asserts here?
340 # [SK, 15 May 2003] I dunno, let's add some...
344 assert built_target == [fff], built_target
345 assert built_source == ["hhh", "iii"], built_source
349 assert built_target == [ggg], built_target
350 assert built_source == ["hhh", "iii"], built_source
356 # NOTE: No env_set()! We should pull the environment from the builder.
357 b.env = Environment()
358 b.overrides = { "on" : 3, "off" : 4 }
362 assert built_target[0] == jjj, built_target[0]
363 assert built_source == [], built_source
364 assert built_args["on"] == 3, built_args
365 assert built_args["off"] == 4, built_args
367 def test_get_build_scanner_path(self):
368 """Test the get_build_scanner_path() method"""
369 n = SCons.Node.Node()
372 p = n.get_build_scanner_path('fake_scanner')
373 assert p == "executor would call fake_scanner", p
375 def test_get_executor(self):
376 """Test the get_executor() method"""
377 n = SCons.Node.Node()
381 except AttributeError:
384 self.fail("did not catch expected AttributeError")
391 n = SCons.Node.Node()
392 n.builder_set(Builder())
394 assert x.env == 'env1', x.env
396 n = SCons.Node.Node()
397 n.builder_set(Builder())
400 assert x.env == 'env2', x.env
402 def test_set_executor(self):
403 """Test the set_executor() method"""
404 n = SCons.Node.Node()
406 assert n.executor == 1, n.executor
408 def test_executor_cleanup(self):
409 """Test letting the executor cleanup its cache"""
410 n = SCons.Node.Node()
416 def test_reset_executor(self):
417 """Test the reset_executor() method"""
418 n = SCons.Node.Node()
420 assert n.executor == 1, n.executor
422 assert not hasattr(n, 'executor'), "unexpected executor attribute"
424 def test_built(self):
425 """Test the built() method"""
426 class SubNodeInfo(SCons.Node.NodeInfoBase):
427 def update(self, node):
429 class SubNode(SCons.Node.Node):
434 n.ninfo = SubNodeInfo(n)
436 assert n.cleared, n.cleared
437 assert n.ninfo.updated, n.ninfo.cleared
439 def test_push_to_cache(self):
440 """Test the base push_to_cache() method"""
441 n = SCons.Node.Node()
442 r = n.push_to_cache()
445 def test_retrieve_from_cache(self):
446 """Test the base retrieve_from_cache() method"""
447 n = SCons.Node.Node()
448 r = n.retrieve_from_cache()
451 def test_visited(self):
452 """Test the base visited() method
454 Just make sure it's there and we can call it.
456 n = SCons.Node.Node()
459 def test_builder_set(self):
460 """Test setting a Node's Builder
462 node = SCons.Node.Node()
465 assert node.builder == b
467 def test_has_builder(self):
468 """Test the has_builder() method
470 n1 = SCons.Node.Node()
471 assert n1.has_builder() == 0
472 n1.builder_set(Builder())
473 assert n1.has_builder() == 1
475 def test_has_explicit_builder(self):
476 """Test the has_explicit_builder() method
478 n1 = SCons.Node.Node()
479 assert not n1.has_explicit_builder()
481 assert n1.has_explicit_builder()
482 n1.set_explicit(None)
483 assert not n1.has_explicit_builder()
485 def test_get_builder(self):
486 """Test the get_builder() method"""
487 n1 = SCons.Node.Node()
490 b = n1.get_builder(777)
495 b = n1.get_builder(999)
498 def test_multiple_side_effect_has_builder(self):
499 """Test the multiple_side_effect_has_builder() method
501 n1 = SCons.Node.Node()
502 assert n1.multiple_side_effect_has_builder() == 0
503 n1.builder_set(Builder())
504 assert n1.multiple_side_effect_has_builder() == 1
506 def test_is_derived(self):
507 """Test the is_derived() method
509 n1 = SCons.Node.Node()
510 n2 = SCons.Node.Node()
511 n3 = SCons.Node.Node()
513 n2.builder_set(Builder())
516 assert n1.is_derived() == 0
517 assert n2.is_derived() == 1
518 assert n3.is_derived() == 1
520 def test_alter_targets(self):
521 """Test the alter_targets() method
523 n = SCons.Node.Node()
524 t, m = n.alter_targets()
528 def test_is_up_to_date(self):
529 """Test the default is_up_to_date() method
531 node = SCons.Node.Node()
532 assert node.is_up_to_date() is None
534 def test_children_are_up_to_date(self):
535 """Test the children_are_up_to_date() method used by subclasses
537 n1 = SCons.Node.Node()
538 n2 = SCons.Node.Node()
541 assert n1.children_are_up_to_date(), "expected up to date"
542 n2.set_state(SCons.Node.executed)
543 assert not n1.children_are_up_to_date(), "expected not up to date"
544 n2.set_state(SCons.Node.up_to_date)
545 assert n1.children_are_up_to_date(), "expected up to date"
547 assert not n1.children_are_up_to_date(), "expected not up to date"
549 def test_env_set(self):
550 """Test setting a Node's Environment
552 node = SCons.Node.Node()
557 def test_get_actions(self):
558 """Test fetching a Node's action list
560 node = SCons.Node.Node()
561 node.builder_set(Builder())
562 a = node.builder.get_actions()
563 assert isinstance(a[0], MyAction), a[0]
565 def test_get_csig(self):
566 """Test generic content signature calculation
568 node = SCons.Node.Node()
569 node.get_contents = lambda: 444
570 result = node.get_csig()
571 assert result == '550a141f12de6341fba65b0ad0433500', result
573 def test_get_cachedir_csig(self):
574 """Test content signature calculation for CacheDir
576 node = SCons.Node.Node()
577 node.get_contents = lambda: 555
578 result = node.get_cachedir_csig()
579 assert result == '15de21c670ae7c3f6f3f1f37029303c9', result
581 def test_get_binfo(self):
582 """Test fetching/creating a build information structure
584 node = SCons.Node.Node()
586 binfo = node.get_binfo()
587 assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo
589 node = SCons.Node.Node()
590 d = SCons.Node.Node()
591 d.get_ninfo().csig = 777
592 i = SCons.Node.Node()
593 i.get_ninfo().csig = 888
597 binfo = node.get_binfo()
598 assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo
599 assert hasattr(binfo, 'bsources')
600 assert hasattr(binfo, 'bsourcesigs')
601 assert binfo.bdepends == [d]
602 assert hasattr(binfo, 'bdependsigs')
603 assert binfo.bimplicit == [i]
604 assert hasattr(binfo, 'bimplicitsigs')
606 def test_explain(self):
607 """Test explaining why a Node must be rebuilt
609 class testNode(SCons.Node.Node):
610 def __str__(self): return 'xyzzy'
612 node.exists = lambda: None
613 # Can't do this with new-style classes (python bug #1066490)
614 #node.__str__ = lambda: 'xyzzy'
615 result = node.explain()
616 assert result == "building `xyzzy' because it doesn't exist\n", result
618 class testNode2(SCons.Node.Node):
619 def __str__(self): return 'null_binfo'
624 node.fs.Top = SCons.Node.Node()
625 result = node.explain()
626 assert result is None, result
629 class Null_SConsignEntry:
630 class Null_BuildInfo:
631 def prepare_dependencies(self):
633 binfo = Null_BuildInfo()
634 return Null_SConsignEntry()
636 node.get_stored_info = get_null_info
637 #see above: node.__str__ = lambda: 'null_binfo'
638 result = node.explain()
639 assert result == "Cannot explain why `null_binfo' is being rebuilt: No previous build information found\n", result
641 # XXX additional tests for the guts of the functionality some day
643 #def test_del_binfo(self):
644 # """Test deleting the build information from a Node
646 # node = SCons.Node.Node()
649 # assert not hasattr(node, 'binfo'), node
651 def test_store_info(self):
652 """Test calling the method to store build information
654 node = SCons.Node.Node()
657 def test_get_stored_info(self):
658 """Test calling the method to fetch stored build information
660 node = SCons.Node.Node()
661 result = node.get_stored_info()
662 assert result is None, result
664 def test_set_always_build(self):
665 """Test setting a Node's always_build value
667 node = SCons.Node.Node()
668 node.set_always_build()
669 assert node.always_build
670 node.set_always_build(3)
671 assert node.always_build == 3
673 def test_set_noclean(self):
674 """Test setting a Node's noclean value
676 node = SCons.Node.Node()
678 assert node.noclean == 1, node.noclean
680 assert node.noclean == 1, node.noclean
682 assert node.noclean == 0, node.noclean
683 node.set_noclean(None)
684 assert node.noclean == 0, node.noclean
686 def test_set_precious(self):
687 """Test setting a Node's precious value
689 node = SCons.Node.Node()
693 assert node.precious == 7
695 def test_exists(self):
696 """Test evaluating whether a Node exists.
698 node = SCons.Node.Node()
702 def test_exists(self):
703 """Test evaluating whether a Node exists locally or in a repository.
705 node = SCons.Node.Node()
709 class MyNode(SCons.Node.Node):
717 def test_prepare(self):
718 """Test preparing a node to be built
720 By extension, this also tests the missing() method.
722 node = SCons.Node.Node()
724 n1 = SCons.Node.Node()
725 n1.builder_set(Builder())
727 node.implicit_set = set()
728 node._add_child(node.implicit, node.implicit_set, [n1])
730 node.prepare() # should not throw an exception
732 n2 = SCons.Node.Node()
735 node.implicit_set = set()
736 node._add_child(node.implicit, node.implicit_set, [n2])
738 node.prepare() # should not throw an exception
740 n3 = SCons.Node.Node()
742 node.implicit_set = set()
743 node._add_child(node.implicit, node.implicit_set, [n3])
745 node.prepare() # should not throw an exception
747 class MyNode(SCons.Node.Node):
752 node.implicit_set = set()
753 node._add_child(node.implicit, node.implicit_set, [n4])
757 except SCons.Errors.StopError:
759 assert exc_caught, "did not catch expected StopError"
761 def test_add_dependency(self):
762 """Test adding dependencies to a Node's list.
764 node = SCons.Node.Node()
765 assert node.depends == []
767 zero = SCons.Node.Node()
769 one = SCons.Node.Node()
770 two = SCons.Node.Node()
771 three = SCons.Node.Node()
772 four = SCons.Node.Node()
773 five = SCons.Node.Node()
774 six = SCons.Node.Node()
776 node.add_dependency([zero])
777 assert node.depends == [zero]
778 node.add_dependency([one])
779 assert node.depends == [zero, one]
780 node.add_dependency([two, three])
781 assert node.depends == [zero, one, two, three]
782 node.add_dependency([three, four, one])
783 assert node.depends == [zero, one, two, three, four]
786 node.add_depends([[five, six]])
790 raise "did not catch expected exception"
791 assert node.depends == [zero, one, two, three, four]
794 def test_add_source(self):
795 """Test adding sources to a Node's list.
797 node = SCons.Node.Node()
798 assert node.sources == []
800 zero = SCons.Node.Node()
801 one = SCons.Node.Node()
802 two = SCons.Node.Node()
803 three = SCons.Node.Node()
804 four = SCons.Node.Node()
805 five = SCons.Node.Node()
806 six = SCons.Node.Node()
808 node.add_source([zero])
809 assert node.sources == [zero]
810 node.add_source([one])
811 assert node.sources == [zero, one]
812 node.add_source([two, three])
813 assert node.sources == [zero, one, two, three]
814 node.add_source([three, four, one])
815 assert node.sources == [zero, one, two, three, four]
818 node.add_source([[five, six]])
822 raise "did not catch expected exception"
823 assert node.sources == [zero, one, two, three, four], node.sources
825 def test_add_ignore(self):
826 """Test adding files whose dependencies should be ignored.
828 node = SCons.Node.Node()
829 assert node.ignore == []
831 zero = SCons.Node.Node()
832 one = SCons.Node.Node()
833 two = SCons.Node.Node()
834 three = SCons.Node.Node()
835 four = SCons.Node.Node()
836 five = SCons.Node.Node()
837 six = SCons.Node.Node()
839 node.add_ignore([zero])
840 assert node.ignore == [zero]
841 node.add_ignore([one])
842 assert node.ignore == [zero, one]
843 node.add_ignore([two, three])
844 assert node.ignore == [zero, one, two, three]
845 node.add_ignore([three, four, one])
846 assert node.ignore == [zero, one, two, three, four]
849 node.add_ignore([[five, six]])
853 raise "did not catch expected exception"
854 assert node.ignore == [zero, one, two, three, four]
856 def test_get_found_includes(self):
857 """Test the default get_found_includes() method
859 node = SCons.Node.Node()
860 target = SCons.Node.Node()
862 deps = node.get_found_includes(e, None, target)
863 assert deps == [], deps
865 def test_get_implicit_deps(self):
866 """Test get_implicit_deps()
869 target = MyNode("ttt")
872 # No scanner at all returns []
873 deps = node.get_implicit_deps(env, None, target)
874 assert deps == [], deps
879 node.found_includes = [d1, d2]
881 # Simple return of the found includes
882 deps = node.get_implicit_deps(env, s, target)
883 assert deps == [d1, d2], deps
885 # By default, our fake scanner recurses
889 d1.found_includes = [e, f]
890 d2.found_includes = [e, f]
891 f.found_includes = [g]
892 deps = node.get_implicit_deps(env, s, target)
893 assert deps == [d1, d2, e, f, g], list(map(str, deps))
895 # Recursive scanning eliminates duplicates
896 e.found_includes = [f]
897 deps = node.get_implicit_deps(env, s, target)
898 assert deps == [d1, d2, e, f, g], list(map(str, deps))
900 # Scanner method can select specific nodes to recurse
902 return [n for n in nodes if str(n)[0] != 'f']
903 s.recurse_nodes = no_fff
904 deps = node.get_implicit_deps(env, s, target)
905 assert deps == [d1, d2, e, f], list(map(str, deps))
907 # Scanner method can short-circuit recursing entirely
908 s.recurse_nodes = lambda nodes: []
909 deps = node.get_implicit_deps(env, s, target)
910 assert deps == [d1, d2], list(map(str, deps))
912 def test_get_env_scanner(self):
913 """Test fetching the environment scanner for a Node
915 node = SCons.Node.Node()
917 env = Environment(SCANNERS = [scanner])
918 s = node.get_env_scanner(env)
919 assert s == scanner, s
920 s = node.get_env_scanner(env, {'X':1})
921 assert s == scanner, s
923 def test_get_target_scanner(self):
924 """Test fetching the target scanner for a Node
929 n = SCons.Node.Node()
931 x = n.get_target_scanner()
934 def test_get_source_scanner(self):
935 """Test fetching the source scanner for a Node
937 target = SCons.Node.Node()
938 source = SCons.Node.Node()
939 s = target.get_source_scanner(source)
940 assert isinstance(s, SCons.Util.Null), s
946 class Builder1(Builder):
947 def __call__(self, source):
948 r = SCons.Node.Node()
951 class Builder2(Builder1):
952 def __init__(self, scanner):
953 self.source_scanner = scanner
955 builder = Builder2(ts1)
957 targets = builder([source])
958 s = targets[0].get_source_scanner(source)
961 target.builder_set(Builder2(ts1))
962 target.builder.source_scanner = ts2
963 s = target.get_source_scanner(source)
966 builder = Builder1(env=Environment(SCANNERS = [ts3]))
968 targets = builder([source])
970 s = targets[0].get_source_scanner(source)
975 """Test Scanner functionality
979 node.builder = Builder()
981 x = MyExecutor(env, [node])
985 node.found_includes = [d]
987 node.builder.target_scanner = s
988 assert node.implicit is None
992 assert node.implicit == [d], node.implicit
994 # Check that scanning a node with some stored implicit
995 # dependencies resets internal attributes appropriately
996 # if the stored dependencies need recalculation.
997 class StoredNode(MyNode):
998 def get_stored_implicit(self):
999 return [MyNode('implicit1'), MyNode('implicit2')]
1001 save_implicit_cache = SCons.Node.implicit_cache
1002 save_implicit_deps_changed = SCons.Node.implicit_deps_changed
1003 save_implicit_deps_unchanged = SCons.Node.implicit_deps_unchanged
1004 SCons.Node.implicit_cache = 1
1005 SCons.Node.implicit_deps_changed = None
1006 SCons.Node.implicit_deps_unchanged = None
1008 sn = StoredNode("eee")
1009 sn.builder_set(Builder())
1010 sn.builder.target_scanner = s
1014 assert sn.implicit == [], sn.implicit
1015 assert sn.children() == [], sn.children()
1018 SCons.Node.implicit_cache = save_implicit_cache
1019 SCons.Node.implicit_deps_changed = save_implicit_deps_changed
1020 SCons.Node.implicit_deps_unchanged = save_implicit_deps_unchanged
1022 def test_scanner_key(self):
1023 """Test that a scanner_key() method exists"""
1024 assert SCons.Node.Node().scanner_key() is None
1026 def test_children(self):
1027 """Test fetching the non-ignored "children" of a Node.
1029 node = SCons.Node.Node()
1030 n1 = SCons.Node.Node()
1031 n2 = SCons.Node.Node()
1032 n3 = SCons.Node.Node()
1033 n4 = SCons.Node.Node()
1034 n5 = SCons.Node.Node()
1035 n6 = SCons.Node.Node()
1036 n7 = SCons.Node.Node()
1037 n8 = SCons.Node.Node()
1038 n9 = SCons.Node.Node()
1039 n10 = SCons.Node.Node()
1040 n11 = SCons.Node.Node()
1041 n12 = SCons.Node.Node()
1043 node.add_source([n1, n2, n3])
1044 node.add_dependency([n4, n5, n6])
1046 node.implicit_set = set()
1047 node._add_child(node.implicit, node.implicit_set, [n7, n8, n9])
1048 node._add_child(node.implicit, node.implicit_set, [n10, n11, n12])
1049 node.add_ignore([n2, n5, n8, n11])
1051 kids = node.children()
1052 for kid in [n1, n3, n4, n6, n7, n9, n10, n12]:
1053 assert kid in kids, kid
1054 for kid in [n2, n5, n8, n11]:
1055 assert not kid in kids, kid
1057 def test_all_children(self):
1058 """Test fetching all the "children" of a Node.
1060 node = SCons.Node.Node()
1061 n1 = SCons.Node.Node()
1062 n2 = SCons.Node.Node()
1063 n3 = SCons.Node.Node()
1064 n4 = SCons.Node.Node()
1065 n5 = SCons.Node.Node()
1066 n6 = SCons.Node.Node()
1067 n7 = SCons.Node.Node()
1068 n8 = SCons.Node.Node()
1069 n9 = SCons.Node.Node()
1070 n10 = SCons.Node.Node()
1071 n11 = SCons.Node.Node()
1072 n12 = SCons.Node.Node()
1074 node.add_source([n1, n2, n3])
1075 node.add_dependency([n4, n5, n6])
1077 node.implicit_set = set()
1078 node._add_child(node.implicit, node.implicit_set, [n7, n8, n9])
1079 node._add_child(node.implicit, node.implicit_set, [n10, n11, n12])
1080 node.add_ignore([n2, n5, n8, n11])
1082 kids = node.all_children()
1083 for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12]:
1084 assert kid in kids, kid
1086 def test_state(self):
1087 """Test setting and getting the state of a node
1089 node = SCons.Node.Node()
1090 assert node.get_state() == SCons.Node.no_state
1091 node.set_state(SCons.Node.executing)
1092 assert node.get_state() == SCons.Node.executing
1093 assert SCons.Node.pending < SCons.Node.executing
1094 assert SCons.Node.executing < SCons.Node.up_to_date
1095 assert SCons.Node.up_to_date < SCons.Node.executed
1096 assert SCons.Node.executed < SCons.Node.failed
1098 def test_walker(self):
1099 """Test walking a Node tree.
1104 nw = SCons.Node.Walker(n1)
1105 assert not nw.is_done()
1106 assert nw.get_next().name == "n1"
1108 assert nw.get_next() is None
1112 n1.add_source([n2, n3])
1114 nw = SCons.Node.Walker(n1)
1116 assert n.name == "n2", n.name
1118 assert n.name == "n3", n.name
1120 assert n.name == "n1", n.name
1128 n2.add_source([n4, n5])
1129 n3.add_dependency([n6, n7])
1131 nw = SCons.Node.Walker(n1)
1132 assert nw.get_next().name == "n4"
1133 assert nw.get_next().name == "n5"
1134 assert n2 in nw.history
1135 assert nw.get_next().name == "n2"
1136 assert nw.get_next().name == "n6"
1137 assert nw.get_next().name == "n7"
1138 assert n3 in nw.history
1139 assert nw.get_next().name == "n3"
1140 assert n1 in nw.history
1141 assert nw.get_next().name == "n1"
1142 assert nw.get_next() is None
1145 n8.add_dependency([n3])
1146 n7.add_dependency([n8])
1148 def cycle(node, stack):
1149 global cycle_detected
1152 global cycle_detected
1154 nw = SCons.Node.Walker(n3, cycle_func = cycle)
1156 assert n.name == "n6", n.name
1158 assert n.name == "n8", n.name
1159 assert cycle_detected
1160 cycle_detected = None
1162 assert n.name == "n7", n.name
1164 assert nw.get_next() is None
1166 def test_abspath(self):
1167 """Test the get_abspath() method."""
1169 assert n.get_abspath() == str(n), n.get_abspath()
1171 def test_for_signature(self):
1172 """Test the for_signature() method."""
1174 assert n.for_signature() == str(n), n.get_abspath()
1176 def test_get_string(self):
1177 """Test the get_string() method."""
1178 class TestNode(MyNode):
1179 def __init__(self, name, sig):
1180 MyNode.__init__(self, name)
1183 def for_signature(self):
1186 n = TestNode("foo", "bar")
1187 assert n.get_string(0) == "foo", n.get_string(0)
1188 assert n.get_string(1) == "bar", n.get_string(1)
1190 def test_literal(self):
1191 """Test the is_literal() function."""
1193 assert n.is_literal()
1195 def test_Annotate(self):
1196 """Test using an interface-specific Annotate function."""
1197 def my_annotate(node, self=self):
1198 node.annotation = self.node_string
1200 save_Annotate = SCons.Node.Annotate
1201 SCons.Node.Annotate = my_annotate
1204 self.node_string = '#1'
1205 n = SCons.Node.Node()
1206 assert n.annotation == '#1', n.annotation
1208 self.node_string = '#2'
1209 n = SCons.Node.Node()
1210 assert n.annotation == '#2', n.annotation
1212 SCons.Node.Annotate = save_Annotate
1214 def test_clear(self):
1215 """Test clearing all cached state information."""
1216 n = SCons.Node.Node()
1220 n.includes = 'testincludes'
1221 n.found_include = {'testkey':'testvalue'}
1222 n.implicit = 'testimplicit'
1229 assert n.includes is None, n.includes
1232 def test_get_subst_proxy(self):
1233 """Test the get_subst_proxy method."""
1236 assert n.get_subst_proxy() == n, n.get_subst_proxy()
1238 def test_new_binfo(self):
1239 """Test the new_binfo() method"""
1240 n = SCons.Node.Node()
1241 result = n.new_binfo()
1242 assert isinstance(result, SCons.Node.BuildInfoBase), result
1244 def test_get_suffix(self):
1245 """Test the base Node get_suffix() method"""
1246 n = SCons.Node.Node()
1250 def test_postprocess(self):
1251 """Test calling the base Node postprocess() method"""
1252 n = SCons.Node.Node()
1253 n.waiting_parents = set( ['foo','bar'] )
1256 assert n.waiting_parents == set(), n.waiting_parents
1258 def test_add_to_waiting_parents(self):
1259 """Test the add_to_waiting_parents() method"""
1260 n1 = SCons.Node.Node()
1261 n2 = SCons.Node.Node()
1262 assert n1.waiting_parents == set(), n1.waiting_parents
1263 r = n1.add_to_waiting_parents(n2)
1265 assert n1.waiting_parents == set((n2,)), n1.waiting_parents
1266 r = n1.add_to_waiting_parents(n2)
1270 class NodeListTestCase(unittest.TestCase):
1271 def test___str__(self):
1276 nl = SCons.Node.NodeList([n3, n2, n1])
1279 ul = collections.UserList([2])
1283 # An older version of Python (*cough* 1.5.2 *cough*)
1284 # that doesn't allow UserList objects to extend lists.
1288 assert s == "['n3', 'n2', 'n1']", s
1291 r = re.sub('at (0[xX])?[0-9a-fA-F]+', 'at 0x', r)
1292 # Don't care about ancestry: just leaf value of MyNode
1293 r = re.sub('<.*?\.MyNode', '<MyNode', r)
1294 # New-style classes report as "object"; classic classes report
1296 r = re.sub("object", "instance", r)
1297 l = ", ".join(["<MyNode instance at 0x>"]*3)
1298 assert r == '[%s]' % l, r
1302 if __name__ == "__main__":
1303 suite = unittest.TestSuite()
1304 tclasses = [ BuildInfoBaseTestCase,
1305 NodeInfoBaseTestCase,
1308 for tclass in tclasses:
1309 names = unittest.getTestCaseNames(tclass, 'test_')
1310 suite.addTests(list(map(tclass, names)))
1311 if not unittest.TextTestRunner().run(suite).wasSuccessful():
1316 # indent-tabs-mode:nil
1318 # vim: set expandtab tabstop=4 shiftwidth=4: