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__"
46 def _actionAppend(a1, a2):
48 for curr_a in [a1, a2]:
49 if isinstance(curr_a, MyAction):
51 elif isinstance(curr_a, MyListAction):
52 all.extend(curr_a.list)
53 elif type(curr_a) == type([1,2]):
56 raise 'Cannot Combine Actions'
57 return MyListAction(all)
60 def __add__(self, other):
61 return _actionAppend(self, other)
63 def __radd__(self, other):
64 return _actionAppend(other, self)
66 class MyAction(MyActionBase):
70 def __call__(self, target, source, env, executor=None):
71 global built_it, built_target, built_source, built_args, built_order
73 target = executor.get_all_targets()
74 source = executor.get_all_sources()
79 built_order = built_order + 1
80 self.order = built_order
83 def get_implicit_deps(self, target, source, env):
87 def __init__(self, env=None, targets=[], sources=[]):
89 self.targets = targets
90 self.sources = sources
91 def get_build_env(self):
93 def get_build_scanner_path(self, scanner):
94 return 'executor would call %s' % scanner
97 def scan_targets(self, scanner):
100 d = scanner(self.targets)
101 for t in self.targets:
103 def scan_sources(self, scanner):
106 d = scanner(self.sources)
107 for t in self.targets:
110 class MyListAction(MyActionBase):
111 def __init__(self, list):
113 def __call__(self, target, source, env):
115 A(target, source, env)
118 def __init__(self, **kw):
120 self._dict.update(kw)
121 def __getitem__(self, key):
122 return self._dict[key]
123 def Dictionary(self, *args):
125 def Override(self, overrides):
126 d = self._dict.copy()
128 return Environment(**d)
129 def _update(self, dict):
130 self._dict.update(dict)
131 def get_factory(self, factory):
132 return factory or MyNode
133 def get_scanner(self, scanner_key):
134 return self._dict['SCANNERS'][0]
137 def __init__(self, env=None, is_explicit=1):
138 if env is None: env = Environment()
141 self.action = MyAction()
142 self.source_factory = MyNode
143 self.is_explicit = is_explicit
144 self.target_scanner = None
145 self.source_scanner = None
146 def targets(self, t):
148 def get_actions(self):
150 def get_contents(self, target, source, env):
153 class NoneBuilder(Builder):
154 def execute(self, target, source, env):
155 Builder.execute(self, target, source, env)
158 class ListBuilder(Builder):
159 def __init__(self, *nodes):
160 Builder.__init__(self)
162 def execute(self, target, source, env):
163 if hasattr(self, 'status'):
167 target = self.nodes[0]
168 self.status = Builder.execute(self, target, source, env)
171 def execute(self, target, source, env):
175 def execute(self, target, source, env):
176 raise SCons.Errors.BuildError
178 class ExceptBuilder2:
179 def execute(self, target, source, env):
184 def __call__(self, node):
186 return node.found_includes
187 def path(self, env, dir, target=None, source=None):
189 def select(self, node):
191 def recurse_nodes(self, nodes):
194 class MyNode(SCons.Node.Node):
195 """The base Node class contains a number of do-nothing methods that
196 we expect to be overridden by real, functional Node subclasses. So
197 simulate a real, functional Node subclass.
199 def __init__(self, name):
200 SCons.Node.Node.__init__(self)
202 self.found_includes = []
205 def get_found_includes(self, env, scanner, target):
209 def __init__(self, val):
212 def __init__(self, val):
214 def signature(self, args):
216 def collect(self, args):
217 return reduce(lambda x, y: x+y, args, self.val)
222 class NodeInfoBaseTestCase(unittest.TestCase):
224 def test_merge(self):
225 """Test merging NodeInfoBase attributes"""
226 ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node())
227 ni2 = SCons.Node.NodeInfoBase(SCons.Node.Node())
236 expect = {'a1':1, 'a2':222, 'a3':333, '_version_id':1}
237 assert ni1.__dict__ == expect, ni1.__dict__
239 def test_update(self):
240 """Test the update() method"""
241 ni = SCons.Node.NodeInfoBase(SCons.Node.Node())
242 ni.update(SCons.Node.Node())
244 def test_format(self):
245 """Test the NodeInfoBase.format() method"""
246 ni1 = SCons.Node.NodeInfoBase(SCons.Node.Node())
252 assert f == ['1', 'x', 'y', 'z'], f
254 ni1.field_list = ['xxx', 'zzz', 'aaa']
257 assert f == ['x', 'z', 'None'], f
261 class BuildInfoBaseTestCase(unittest.TestCase):
263 def test___init__(self):
264 """Test BuildInfoBase initialization"""
265 n = SCons.Node.Node()
266 bi = SCons.Node.BuildInfoBase(n)
269 def test_merge(self):
270 """Test merging BuildInfoBase attributes"""
271 n1 = SCons.Node.Node()
272 bi1 = SCons.Node.BuildInfoBase(n1)
273 n2 = SCons.Node.Node()
274 bi2 = SCons.Node.BuildInfoBase(n2)
283 assert bi1.a1 == 1, bi1.a1
284 assert bi1.a2 == 222, bi1.a2
285 assert bi1.a3 == 333, bi1.a3
288 class NodeTestCase(unittest.TestCase):
290 def test_build(self):
291 """Test building a node
293 global built_it, built_order
295 # Make sure it doesn't blow up if no builder is set.
298 assert built_it is None
299 node.build(extra_kw_argument = 1)
300 assert built_it is None
303 node.builder_set(Builder())
304 node.env_set(Environment())
306 node.sources = ["yyy", "zzz"]
309 assert built_target == [node], built_target
310 assert built_source == ["yyy", "zzz"], built_source
314 node.builder_set(NoneBuilder())
315 node.env_set(Environment())
317 node.sources = ["rrr", "sss"]
318 node.builder.overrides = { "foo" : 1, "bar" : 2 }
321 assert built_target == [node], built_target
322 assert built_source == ["rrr", "sss"], built_source
323 assert built_args["foo"] == 1, built_args
324 assert built_args["bar"] == 2, built_args
328 lb = ListBuilder(fff, ggg)
336 fff.sources = ["hhh", "iii"]
337 ggg.sources = ["hhh", "iii"]
338 # [Charles C. 1/7/2002] Uhhh, why are there no asserts here?
339 # [SK, 15 May 2003] I dunno, let's add some...
343 assert built_target == [fff], built_target
344 assert built_source == ["hhh", "iii"], built_source
348 assert built_target == [ggg], built_target
349 assert built_source == ["hhh", "iii"], built_source
355 # NOTE: No env_set()! We should pull the environment from the builder.
356 b.env = Environment()
357 b.overrides = { "on" : 3, "off" : 4 }
361 assert built_target[0] == jjj, built_target[0]
362 assert built_source == [], built_source
363 assert built_args["on"] == 3, built_args
364 assert built_args["off"] == 4, built_args
366 def test_get_build_scanner_path(self):
367 """Test the get_build_scanner_path() method"""
368 n = SCons.Node.Node()
371 p = n.get_build_scanner_path('fake_scanner')
372 assert p == "executor would call fake_scanner", p
374 def test_get_executor(self):
375 """Test the get_executor() method"""
376 n = SCons.Node.Node()
380 except AttributeError:
383 self.fail("did not catch expected AttributeError")
390 n = SCons.Node.Node()
391 n.builder_set(Builder())
393 assert x.env == 'env1', x.env
395 n = SCons.Node.Node()
396 n.builder_set(Builder())
399 assert x.env == 'env2', x.env
401 def test_set_executor(self):
402 """Test the set_executor() method"""
403 n = SCons.Node.Node()
405 assert n.executor == 1, n.executor
407 def test_executor_cleanup(self):
408 """Test letting the executor cleanup its cache"""
409 n = SCons.Node.Node()
415 def test_reset_executor(self):
416 """Test the reset_executor() method"""
417 n = SCons.Node.Node()
419 assert n.executor == 1, n.executor
421 assert not hasattr(n, 'executor'), "unexpected executor attribute"
423 def test_built(self):
424 """Test the built() method"""
425 class SubNodeInfo(SCons.Node.NodeInfoBase):
426 def update(self, node):
428 class SubNode(SCons.Node.Node):
433 n.ninfo = SubNodeInfo(n)
435 assert n.cleared, n.cleared
436 assert n.ninfo.updated, n.ninfo.cleared
438 def test_push_to_cache(self):
439 """Test the base push_to_cache() method"""
440 n = SCons.Node.Node()
441 r = n.push_to_cache()
444 def test_retrieve_from_cache(self):
445 """Test the base retrieve_from_cache() method"""
446 n = SCons.Node.Node()
447 r = n.retrieve_from_cache()
450 def test_visited(self):
451 """Test the base visited() method
453 Just make sure it's there and we can call it.
455 n = SCons.Node.Node()
458 def test_builder_set(self):
459 """Test setting a Node's Builder
461 node = SCons.Node.Node()
464 assert node.builder == b
466 def test_has_builder(self):
467 """Test the has_builder() method
469 n1 = SCons.Node.Node()
470 assert n1.has_builder() == 0
471 n1.builder_set(Builder())
472 assert n1.has_builder() == 1
474 def test_has_explicit_builder(self):
475 """Test the has_explicit_builder() method
477 n1 = SCons.Node.Node()
478 assert not n1.has_explicit_builder()
480 assert n1.has_explicit_builder()
481 n1.set_explicit(None)
482 assert not n1.has_explicit_builder()
484 def test_get_builder(self):
485 """Test the get_builder() method"""
486 n1 = SCons.Node.Node()
489 b = n1.get_builder(777)
494 b = n1.get_builder(999)
497 def test_multiple_side_effect_has_builder(self):
498 """Test the multiple_side_effect_has_builder() method
500 n1 = SCons.Node.Node()
501 assert n1.multiple_side_effect_has_builder() == 0
502 n1.builder_set(Builder())
503 assert n1.multiple_side_effect_has_builder() == 1
505 def test_is_derived(self):
506 """Test the is_derived() method
508 n1 = SCons.Node.Node()
509 n2 = SCons.Node.Node()
510 n3 = SCons.Node.Node()
512 n2.builder_set(Builder())
515 assert n1.is_derived() == 0
516 assert n2.is_derived() == 1
517 assert n3.is_derived() == 1
519 def test_alter_targets(self):
520 """Test the alter_targets() method
522 n = SCons.Node.Node()
523 t, m = n.alter_targets()
527 def test_is_up_to_date(self):
528 """Test the default is_up_to_date() method
530 node = SCons.Node.Node()
531 assert node.is_up_to_date() is None
533 def test_children_are_up_to_date(self):
534 """Test the children_are_up_to_date() method used by subclasses
536 n1 = SCons.Node.Node()
537 n2 = SCons.Node.Node()
540 assert n1.children_are_up_to_date(), "expected up to date"
541 n2.set_state(SCons.Node.executed)
542 assert not n1.children_are_up_to_date(), "expected not up to date"
543 n2.set_state(SCons.Node.up_to_date)
544 assert n1.children_are_up_to_date(), "expected up to date"
546 assert not n1.children_are_up_to_date(), "expected not up to date"
548 def test_env_set(self):
549 """Test setting a Node's Environment
551 node = SCons.Node.Node()
556 def test_get_actions(self):
557 """Test fetching a Node's action list
559 node = SCons.Node.Node()
560 node.builder_set(Builder())
561 a = node.builder.get_actions()
562 assert isinstance(a[0], MyAction), a[0]
564 def test_get_csig(self):
565 """Test generic content signature calculation
567 node = SCons.Node.Node()
568 node.get_contents = lambda: 444
569 result = node.get_csig()
570 assert result == '550a141f12de6341fba65b0ad0433500', result
572 def test_get_cachedir_csig(self):
573 """Test content signature calculation for CacheDir
575 node = SCons.Node.Node()
576 node.get_contents = lambda: 555
577 result = node.get_cachedir_csig()
578 assert result == '15de21c670ae7c3f6f3f1f37029303c9', result
580 def test_get_binfo(self):
581 """Test fetching/creating a build information structure
583 node = SCons.Node.Node()
585 binfo = node.get_binfo()
586 assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo
588 node = SCons.Node.Node()
589 d = SCons.Node.Node()
590 d.get_ninfo().csig = 777
591 i = SCons.Node.Node()
592 i.get_ninfo().csig = 888
596 binfo = node.get_binfo()
597 assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo
598 assert hasattr(binfo, 'bsources')
599 assert hasattr(binfo, 'bsourcesigs')
600 assert binfo.bdepends == [d]
601 assert hasattr(binfo, 'bdependsigs')
602 assert binfo.bimplicit == [i]
603 assert hasattr(binfo, 'bimplicitsigs')
605 def test_explain(self):
606 """Test explaining why a Node must be rebuilt
608 class testNode(SCons.Node.Node):
609 def __str__(self): return 'xyzzy'
611 node.exists = lambda: None
612 # Can't do this with new-style classes (python bug #1066490)
613 #node.__str__ = lambda: 'xyzzy'
614 result = node.explain()
615 assert result == "building `xyzzy' because it doesn't exist\n", result
617 class testNode2(SCons.Node.Node):
618 def __str__(self): return 'null_binfo'
623 node.fs.Top = SCons.Node.Node()
624 result = node.explain()
625 assert result is None, result
628 class Null_SConsignEntry:
629 class Null_BuildInfo:
630 def prepare_dependencies(self):
632 binfo = Null_BuildInfo()
633 return Null_SConsignEntry()
635 node.get_stored_info = get_null_info
636 #see above: node.__str__ = lambda: 'null_binfo'
637 result = node.explain()
638 assert result == "Cannot explain why `null_binfo' is being rebuilt: No previous build information found\n", result
640 # XXX additional tests for the guts of the functionality some day
642 #def test_del_binfo(self):
643 # """Test deleting the build information from a Node
645 # node = SCons.Node.Node()
648 # assert not hasattr(node, 'binfo'), node
650 def test_store_info(self):
651 """Test calling the method to store build information
653 node = SCons.Node.Node()
656 def test_get_stored_info(self):
657 """Test calling the method to fetch stored build information
659 node = SCons.Node.Node()
660 result = node.get_stored_info()
661 assert result is None, result
663 def test_set_always_build(self):
664 """Test setting a Node's always_build value
666 node = SCons.Node.Node()
667 node.set_always_build()
668 assert node.always_build
669 node.set_always_build(3)
670 assert node.always_build == 3
672 def test_set_noclean(self):
673 """Test setting a Node's noclean value
675 node = SCons.Node.Node()
677 assert node.noclean == 1, node.noclean
679 assert node.noclean == 1, node.noclean
681 assert node.noclean == 0, node.noclean
682 node.set_noclean(None)
683 assert node.noclean == 0, node.noclean
685 def test_set_precious(self):
686 """Test setting a Node's precious value
688 node = SCons.Node.Node()
692 assert node.precious == 7
694 def test_exists(self):
695 """Test evaluating whether a Node exists.
697 node = SCons.Node.Node()
701 def test_exists(self):
702 """Test evaluating whether a Node exists locally or in a repository.
704 node = SCons.Node.Node()
708 class MyNode(SCons.Node.Node):
716 def test_prepare(self):
717 """Test preparing a node to be built
719 By extension, this also tests the missing() method.
721 node = SCons.Node.Node()
723 n1 = SCons.Node.Node()
724 n1.builder_set(Builder())
726 node.implicit_set = set()
727 node._add_child(node.implicit, node.implicit_set, [n1])
729 node.prepare() # should not throw an exception
731 n2 = SCons.Node.Node()
734 node.implicit_set = set()
735 node._add_child(node.implicit, node.implicit_set, [n2])
737 node.prepare() # should not throw an exception
739 n3 = SCons.Node.Node()
741 node.implicit_set = set()
742 node._add_child(node.implicit, node.implicit_set, [n3])
744 node.prepare() # should not throw an exception
746 class MyNode(SCons.Node.Node):
751 node.implicit_set = set()
752 node._add_child(node.implicit, node.implicit_set, [n4])
756 except SCons.Errors.StopError:
758 assert exc_caught, "did not catch expected StopError"
760 def test_add_dependency(self):
761 """Test adding dependencies to a Node's list.
763 node = SCons.Node.Node()
764 assert node.depends == []
766 zero = SCons.Node.Node()
768 one = SCons.Node.Node()
769 two = SCons.Node.Node()
770 three = SCons.Node.Node()
771 four = SCons.Node.Node()
772 five = SCons.Node.Node()
773 six = SCons.Node.Node()
775 node.add_dependency([zero])
776 assert node.depends == [zero]
777 node.add_dependency([one])
778 assert node.depends == [zero, one]
779 node.add_dependency([two, three])
780 assert node.depends == [zero, one, two, three]
781 node.add_dependency([three, four, one])
782 assert node.depends == [zero, one, two, three, four]
785 node.add_depends([[five, six]])
789 raise "did not catch expected exception"
790 assert node.depends == [zero, one, two, three, four]
793 def test_add_source(self):
794 """Test adding sources to a Node's list.
796 node = SCons.Node.Node()
797 assert node.sources == []
799 zero = SCons.Node.Node()
800 one = SCons.Node.Node()
801 two = SCons.Node.Node()
802 three = SCons.Node.Node()
803 four = SCons.Node.Node()
804 five = SCons.Node.Node()
805 six = SCons.Node.Node()
807 node.add_source([zero])
808 assert node.sources == [zero]
809 node.add_source([one])
810 assert node.sources == [zero, one]
811 node.add_source([two, three])
812 assert node.sources == [zero, one, two, three]
813 node.add_source([three, four, one])
814 assert node.sources == [zero, one, two, three, four]
817 node.add_source([[five, six]])
821 raise "did not catch expected exception"
822 assert node.sources == [zero, one, two, three, four], node.sources
824 def test_add_ignore(self):
825 """Test adding files whose dependencies should be ignored.
827 node = SCons.Node.Node()
828 assert node.ignore == []
830 zero = SCons.Node.Node()
831 one = SCons.Node.Node()
832 two = SCons.Node.Node()
833 three = SCons.Node.Node()
834 four = SCons.Node.Node()
835 five = SCons.Node.Node()
836 six = SCons.Node.Node()
838 node.add_ignore([zero])
839 assert node.ignore == [zero]
840 node.add_ignore([one])
841 assert node.ignore == [zero, one]
842 node.add_ignore([two, three])
843 assert node.ignore == [zero, one, two, three]
844 node.add_ignore([three, four, one])
845 assert node.ignore == [zero, one, two, three, four]
848 node.add_ignore([[five, six]])
852 raise "did not catch expected exception"
853 assert node.ignore == [zero, one, two, three, four]
855 def test_get_found_includes(self):
856 """Test the default get_found_includes() method
858 node = SCons.Node.Node()
859 target = SCons.Node.Node()
861 deps = node.get_found_includes(e, None, target)
862 assert deps == [], deps
864 def test_get_implicit_deps(self):
865 """Test get_implicit_deps()
868 target = MyNode("ttt")
871 # No scanner at all returns []
872 deps = node.get_implicit_deps(env, None, target)
873 assert deps == [], deps
878 node.found_includes = [d1, d2]
880 # Simple return of the found includes
881 deps = node.get_implicit_deps(env, s, target)
882 assert deps == [d1, d2], deps
884 # By default, our fake scanner recurses
888 d1.found_includes = [e, f]
889 d2.found_includes = [e, f]
890 f.found_includes = [g]
891 deps = node.get_implicit_deps(env, s, target)
892 assert deps == [d1, d2, e, f, g], list(map(str, deps))
894 # Recursive scanning eliminates duplicates
895 e.found_includes = [f]
896 deps = node.get_implicit_deps(env, s, target)
897 assert deps == [d1, d2, e, f, g], list(map(str, deps))
899 # Scanner method can select specific nodes to recurse
901 return [n for n in nodes if str(n)[0] != 'f']
902 s.recurse_nodes = no_fff
903 deps = node.get_implicit_deps(env, s, target)
904 assert deps == [d1, d2, e, f], list(map(str, deps))
906 # Scanner method can short-circuit recursing entirely
907 s.recurse_nodes = lambda nodes: []
908 deps = node.get_implicit_deps(env, s, target)
909 assert deps == [d1, d2], list(map(str, deps))
911 def test_get_env_scanner(self):
912 """Test fetching the environment scanner for a Node
914 node = SCons.Node.Node()
916 env = Environment(SCANNERS = [scanner])
917 s = node.get_env_scanner(env)
918 assert s == scanner, s
919 s = node.get_env_scanner(env, {'X':1})
920 assert s == scanner, s
922 def test_get_target_scanner(self):
923 """Test fetching the target scanner for a Node
928 n = SCons.Node.Node()
930 x = n.get_target_scanner()
933 def test_get_source_scanner(self):
934 """Test fetching the source scanner for a Node
936 target = SCons.Node.Node()
937 source = SCons.Node.Node()
938 s = target.get_source_scanner(source)
939 assert isinstance(s, SCons.Util.Null), s
945 class Builder1(Builder):
946 def __call__(self, source):
947 r = SCons.Node.Node()
950 class Builder2(Builder1):
951 def __init__(self, scanner):
952 self.source_scanner = scanner
954 builder = Builder2(ts1)
956 targets = builder([source])
957 s = targets[0].get_source_scanner(source)
960 target.builder_set(Builder2(ts1))
961 target.builder.source_scanner = ts2
962 s = target.get_source_scanner(source)
965 builder = Builder1(env=Environment(SCANNERS = [ts3]))
967 targets = builder([source])
969 s = targets[0].get_source_scanner(source)
974 """Test Scanner functionality
978 node.builder = Builder()
980 x = MyExecutor(env, [node])
984 node.found_includes = [d]
986 node.builder.target_scanner = s
987 assert node.implicit is None
991 assert node.implicit == [d], node.implicit
993 # Check that scanning a node with some stored implicit
994 # dependencies resets internal attributes appropriately
995 # if the stored dependencies need recalculation.
996 class StoredNode(MyNode):
997 def get_stored_implicit(self):
998 return [MyNode('implicit1'), MyNode('implicit2')]
1000 save_implicit_cache = SCons.Node.implicit_cache
1001 save_implicit_deps_changed = SCons.Node.implicit_deps_changed
1002 save_implicit_deps_unchanged = SCons.Node.implicit_deps_unchanged
1003 SCons.Node.implicit_cache = 1
1004 SCons.Node.implicit_deps_changed = None
1005 SCons.Node.implicit_deps_unchanged = None
1007 sn = StoredNode("eee")
1008 sn.builder_set(Builder())
1009 sn.builder.target_scanner = s
1013 assert sn.implicit == [], sn.implicit
1014 assert sn.children() == [], sn.children()
1017 SCons.Node.implicit_cache = save_implicit_cache
1018 SCons.Node.implicit_deps_changed = save_implicit_deps_changed
1019 SCons.Node.implicit_deps_unchanged = save_implicit_deps_unchanged
1021 def test_scanner_key(self):
1022 """Test that a scanner_key() method exists"""
1023 assert SCons.Node.Node().scanner_key() is None
1025 def test_children(self):
1026 """Test fetching the non-ignored "children" of a Node.
1028 node = SCons.Node.Node()
1029 n1 = SCons.Node.Node()
1030 n2 = SCons.Node.Node()
1031 n3 = SCons.Node.Node()
1032 n4 = SCons.Node.Node()
1033 n5 = SCons.Node.Node()
1034 n6 = SCons.Node.Node()
1035 n7 = SCons.Node.Node()
1036 n8 = SCons.Node.Node()
1037 n9 = SCons.Node.Node()
1038 n10 = SCons.Node.Node()
1039 n11 = SCons.Node.Node()
1040 n12 = SCons.Node.Node()
1042 node.add_source([n1, n2, n3])
1043 node.add_dependency([n4, n5, n6])
1045 node.implicit_set = set()
1046 node._add_child(node.implicit, node.implicit_set, [n7, n8, n9])
1047 node._add_child(node.implicit, node.implicit_set, [n10, n11, n12])
1048 node.add_ignore([n2, n5, n8, n11])
1050 kids = node.children()
1051 for kid in [n1, n3, n4, n6, n7, n9, n10, n12]:
1052 assert kid in kids, kid
1053 for kid in [n2, n5, n8, n11]:
1054 assert not kid in kids, kid
1056 def test_all_children(self):
1057 """Test fetching all the "children" of a Node.
1059 node = SCons.Node.Node()
1060 n1 = SCons.Node.Node()
1061 n2 = SCons.Node.Node()
1062 n3 = SCons.Node.Node()
1063 n4 = SCons.Node.Node()
1064 n5 = SCons.Node.Node()
1065 n6 = SCons.Node.Node()
1066 n7 = SCons.Node.Node()
1067 n8 = SCons.Node.Node()
1068 n9 = SCons.Node.Node()
1069 n10 = SCons.Node.Node()
1070 n11 = SCons.Node.Node()
1071 n12 = SCons.Node.Node()
1073 node.add_source([n1, n2, n3])
1074 node.add_dependency([n4, n5, n6])
1076 node.implicit_set = set()
1077 node._add_child(node.implicit, node.implicit_set, [n7, n8, n9])
1078 node._add_child(node.implicit, node.implicit_set, [n10, n11, n12])
1079 node.add_ignore([n2, n5, n8, n11])
1081 kids = node.all_children()
1082 for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12]:
1083 assert kid in kids, kid
1085 def test_state(self):
1086 """Test setting and getting the state of a node
1088 node = SCons.Node.Node()
1089 assert node.get_state() == SCons.Node.no_state
1090 node.set_state(SCons.Node.executing)
1091 assert node.get_state() == SCons.Node.executing
1092 assert SCons.Node.pending < SCons.Node.executing
1093 assert SCons.Node.executing < SCons.Node.up_to_date
1094 assert SCons.Node.up_to_date < SCons.Node.executed
1095 assert SCons.Node.executed < SCons.Node.failed
1097 def test_walker(self):
1098 """Test walking a Node tree.
1103 nw = SCons.Node.Walker(n1)
1104 assert not nw.is_done()
1105 assert nw.next().name == "n1"
1107 assert nw.next() is None
1111 n1.add_source([n2, n3])
1113 nw = SCons.Node.Walker(n1)
1115 assert n.name == "n2", n.name
1117 assert n.name == "n3", n.name
1119 assert n.name == "n1", n.name
1127 n2.add_source([n4, n5])
1128 n3.add_dependency([n6, n7])
1130 nw = SCons.Node.Walker(n1)
1131 assert nw.next().name == "n4"
1132 assert nw.next().name == "n5"
1133 assert n2 in nw.history
1134 assert nw.next().name == "n2"
1135 assert nw.next().name == "n6"
1136 assert nw.next().name == "n7"
1137 assert n3 in nw.history
1138 assert nw.next().name == "n3"
1139 assert n1 in nw.history
1140 assert nw.next().name == "n1"
1141 assert nw.next() is None
1144 n8.add_dependency([n3])
1145 n7.add_dependency([n8])
1147 def cycle(node, stack):
1148 global cycle_detected
1151 global cycle_detected
1153 nw = SCons.Node.Walker(n3, cycle_func = cycle)
1155 assert n.name == "n6", n.name
1157 assert n.name == "n8", n.name
1158 assert cycle_detected
1159 cycle_detected = None
1161 assert n.name == "n7", n.name
1163 assert nw.next() is None
1165 def test_abspath(self):
1166 """Test the get_abspath() method."""
1168 assert n.get_abspath() == str(n), n.get_abspath()
1170 def test_for_signature(self):
1171 """Test the for_signature() method."""
1173 assert n.for_signature() == str(n), n.get_abspath()
1175 def test_get_string(self):
1176 """Test the get_string() method."""
1177 class TestNode(MyNode):
1178 def __init__(self, name, sig):
1179 MyNode.__init__(self, name)
1182 def for_signature(self):
1185 n = TestNode("foo", "bar")
1186 assert n.get_string(0) == "foo", n.get_string(0)
1187 assert n.get_string(1) == "bar", n.get_string(1)
1189 def test_literal(self):
1190 """Test the is_literal() function."""
1192 assert n.is_literal()
1194 def test_Annotate(self):
1195 """Test using an interface-specific Annotate function."""
1196 def my_annotate(node, self=self):
1197 node.annotation = self.node_string
1199 save_Annotate = SCons.Node.Annotate
1200 SCons.Node.Annotate = my_annotate
1203 self.node_string = '#1'
1204 n = SCons.Node.Node()
1205 assert n.annotation == '#1', n.annotation
1207 self.node_string = '#2'
1208 n = SCons.Node.Node()
1209 assert n.annotation == '#2', n.annotation
1211 SCons.Node.Annotate = save_Annotate
1213 def test_clear(self):
1214 """Test clearing all cached state information."""
1215 n = SCons.Node.Node()
1219 n.includes = 'testincludes'
1220 n.found_include = {'testkey':'testvalue'}
1221 n.implicit = 'testimplicit'
1228 assert n.includes is None, n.includes
1231 def test_get_subst_proxy(self):
1232 """Test the get_subst_proxy method."""
1235 assert n.get_subst_proxy() == n, n.get_subst_proxy()
1237 def test_new_binfo(self):
1238 """Test the new_binfo() method"""
1239 n = SCons.Node.Node()
1240 result = n.new_binfo()
1241 assert isinstance(result, SCons.Node.BuildInfoBase), result
1243 def test_get_suffix(self):
1244 """Test the base Node get_suffix() method"""
1245 n = SCons.Node.Node()
1249 def test_postprocess(self):
1250 """Test calling the base Node postprocess() method"""
1251 n = SCons.Node.Node()
1252 n.waiting_parents = set( ['foo','bar'] )
1255 assert n.waiting_parents == set(), n.waiting_parents
1257 def test_add_to_waiting_parents(self):
1258 """Test the add_to_waiting_parents() method"""
1259 n1 = SCons.Node.Node()
1260 n2 = SCons.Node.Node()
1261 assert n1.waiting_parents == set(), n1.waiting_parents
1262 r = n1.add_to_waiting_parents(n2)
1264 assert n1.waiting_parents == set((n2,)), n1.waiting_parents
1265 r = n1.add_to_waiting_parents(n2)
1269 class NodeListTestCase(unittest.TestCase):
1270 def test___str__(self):
1275 nl = SCons.Node.NodeList([n3, n2, n1])
1278 ul = UserList.UserList([2])
1282 # An older version of Python (*cough* 1.5.2 *cough*)
1283 # that doesn't allow UserList objects to extend lists.
1287 assert s == "['n3', 'n2', 'n1']", s
1290 r = re.sub('at (0[xX])?[0-9a-fA-F]+', 'at 0x', r)
1291 # Don't care about ancestry: just leaf value of MyNode
1292 r = re.sub('<.*?\.MyNode', '<MyNode', r)
1293 # New-style classes report as "object"; classic classes report
1295 r = re.sub("object", "instance", r)
1296 l = ", ".join(["<MyNode instance at 0x>"]*3)
1297 assert r == '[%s]' % l, r
1301 if __name__ == "__main__":
1302 suite = unittest.TestSuite()
1303 tclasses = [ BuildInfoBaseTestCase,
1304 NodeInfoBaseTestCase,
1307 for tclass in tclasses:
1308 names = unittest.getTestCaseNames(tclass, 'test_')
1309 suite.addTests(list(map(tclass, names)))
1310 if not unittest.TextTestRunner().run(suite).wasSuccessful():
1315 # indent-tabs-mode:nil
1317 # vim: set expandtab tabstop=4 shiftwidth=4: