From: stevenknight Date: Sun, 13 Feb 2005 13:05:22 +0000 (+0000) Subject: Refactor Environment/Executor/Node scanner interaction a little. Put --debug={dtree... X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1ae9eb99089b213e1c7fb3e02e6c5745a615213c;p=scons.git Refactor Environment/Executor/Node scanner interaction a little. Put --debug={dtree,includes,stree,tree} in separate tests. git-svn-id: http://scons.tigris.org/svn/scons/trunk@1227 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 013a1258..5b45d552 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -88,20 +88,24 @@ class Executor: cwd = None return scanner.path(env, cwd, self.targets, self.sources) + def get_kw(self, kw={}): + result = self.builder_kw.copy() + result.update(kw) + return result + def do_nothing(self, target, errfunc, kw): pass def do_execute(self, target, errfunc, kw): """Actually execute the action list.""" - kw = kw.copy() - kw.update(self.builder_kw) - apply(self.action, (self.targets, self.sources, - self.get_build_env(), errfunc), kw) + apply(self.action, + (self.targets, self.sources, self.get_build_env(), errfunc), + self.get_kw(kw)) # use extra indirection because with new-style objects (Python 2.2 # and above) we can't override special methods, and nullify() needs # to be able to do this. - + def __call__(self, target, errfunc, **kw): self.do_execute(target, errfunc, kw) @@ -117,7 +121,7 @@ class Executor: self.sources.extend(slist) # another extra indirection for new-style objects and nullify... - + def my_str(self): return self.action.genstring(self.targets, self.sources, @@ -163,7 +167,8 @@ class Executor: if scanner: initial_scanners = lambda src, s=scanner: (src, s) else: - initial_scanners = lambda src, e=env: (src, e.get_scanner(src.scanner_key())) + kw = self.get_kw() + initial_scanners = lambda src, e=env, kw=kw: (src, src.get_scanner(e, kw)) scanner_list = map(initial_scanners, self.sources) scanner_list = filter(remove_null_scanners, scanner_list) scanner_list = map(select_specific_scanner, scanner_list) diff --git a/src/engine/SCons/ExecutorTests.py b/src/engine/SCons/ExecutorTests.py index 189cbad9..d3af914f 100644 --- a/src/engine/SCons/ExecutorTests.py +++ b/src/engine/SCons/ExecutorTests.py @@ -78,8 +78,10 @@ class MyNode: [self], ['s1', 's2']) apply(executor, (self, errfunc), {}) + def get_scanner(self, env, kw): + return MyScanner('dep-') def get_implicit_deps(self, env, scanner, path): - return ['dep-' + str(self)] + return [scanner.prefix + str(self)] def add_to_implicit(self, deps): self.implicit.extend(deps) def missing(self): @@ -88,6 +90,8 @@ class MyNode: return 'cs-'+calc+'-'+self.name class MyScanner: + def __init__(self, prefix): + self.prefix = prefix def path(self, env, cwd, target, source): return () def select(self, node): @@ -162,6 +166,22 @@ class ExecutorTestCase(unittest.TestCase): p = x.get_build_scanner_path(s) assert p == "scanner: sss, here, ['t'], ['s1', 's2']", p + def test_get_kw(self): + """Test the get_kw() method""" + t = MyNode('t') + x = SCons.Executor.Executor(MyAction(), + MyEnvironment(), + [], + [t], + ['s1', 's2'], + builder_kw={'X':1, 'Y':2}) + kw = x.get_kw() + assert kw == {'X':1, 'Y':2}, kw + kw = x.get_kw({'Z':3}) + assert kw == {'X':1, 'Y':2, 'Z':3}, kw + kw = x.get_kw({'X':4}) + assert kw == {'X':4, 'Y':2}, kw + def test__call__(self): """Test calling an Executor""" result = [] @@ -296,9 +316,16 @@ class ExecutorTestCase(unittest.TestCase): targets = [MyNode('t')] sources = [MyNode('s1'), MyNode('s2')] x = SCons.Executor.Executor('b', env, [{}], targets, sources) - scanner = MyScanner() - deps = x.scan(scanner) - assert targets[0].implicit == ['dep-s1', 'dep-s2'], targets[0].implicit + + deps = x.scan(None) + t = targets[0] + assert t.implicit == ['dep-s1', 'dep-s2'], t.implicit + + t.implicit = [] + + deps = x.scan(MyScanner('scanner-')) + t = targets[0] + assert t.implicit == ['scanner-s1', 'scanner-s2'], t.implicit def test_get_missing_sources(self): """Test the ability to check if any sources are missing""" diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 0637cebc..281b5f21 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -830,6 +830,17 @@ class NodeTestCase(unittest.TestCase): deps = node.get_implicit_deps(env, s, target) assert deps == [d, e, f], map(str, deps) + def test_get_scanner(self): + """Test fetching the environment scanner for a Node + """ + node = SCons.Node.Node() + scanner = Scanner() + env = Environment(SCANNERS = [scanner]) + s = node.get_scanner(env) + assert s == scanner, s + s = node.get_scanner(env, {'X':1}) + assert s == scanner, s + def test_get_source_scanner(self): """Test fetching the source scanner for a Node """ diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index c7167a39..96a78cad 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -425,6 +425,8 @@ class Node: """ return self.builder.source_factory(path) + def get_scanner(self, env, kw={}): + return env.get_scanner(self.scanner_key()) def get_source_scanner(self, node): """Fetch the source scanner for the specified node @@ -447,7 +449,7 @@ class Node: # The builder didn't have an explicit scanner, so go look up # a scanner from env['SCANNERS'] based on the node's scanner # key (usually the file extension). - scanner = self.get_build_env().get_scanner(node.scanner_key()) + scanner = self.get_scanner(self.get_build_env()) if scanner: scanner = scanner.select(node) return scanner @@ -758,22 +760,7 @@ class Node: def do_not_ignore(self, node): return node not in self.ignore - def _children_get(self): - "__cacheable__" - children = self.all_children(scan=0) - if self.ignore: - children = filter(self.do_not_ignore, children) - return children - - def children(self, scan=1): - """Return a list of the node's direct children, minus those - that are ignored by this node.""" - if scan: - self.scan() - return self._children_get() - - def all_children(self, scan=1): - """Return a list of all the node's direct children.""" + def _all_children_get(self): # The return list may contain duplicate Nodes, especially in # source trees where there are a lot of repeated #includes # of a tangle of .h files. Profiling shows, however, that @@ -791,13 +778,31 @@ class Node: # using dictionary keys, lose the order, and the only ordered # dictionary patterns I found all ended up using "not in" # internally anyway...) - if scan: - self.scan() if self.implicit is None: return self.sources + self.depends else: return self.sources + self.depends + self.implicit + def _children_get(self): + "__cacheable__" + children = self._all_children_get() + if self.ignore: + children = filter(self.do_not_ignore, children) + return children + + def all_children(self, scan=1): + """Return a list of all the node's direct children.""" + if scan: + self.scan() + return self._all_children_get() + + def children(self, scan=1): + """Return a list of the node's direct children, minus those + that are ignored by this node.""" + if scan: + self.scan() + return self._children_get() + def set_state(self, state): self.state = state diff --git a/test/option--debug.py b/test/option--debug.py index 322afda1..2ded69a1 100644 --- a/test/option--debug.py +++ b/test/option--debug.py @@ -65,154 +65,8 @@ test.write('bar.h', """ #endif """) -test.run(arguments = "--debug=tree foo.xxx") - -tree = """ -+-foo.xxx - +-foo.ooo - | +-foo.c - | +-foo.h - | +-bar.h - +-bar.ooo - +-bar.c - +-bar.h - +-foo.h -""" - -test.fail_test(string.find(test.stdout(), tree) == -1) - -test.run(arguments = "--debug=tree foo.xxx") -test.fail_test(string.find(test.stdout(), tree) == -1) - -stree = """ -[E B C]+-foo.xxx -[E B C] +-foo.ooo -[E ] | +-foo.c -[E ] | +-foo.h -[E ] | +-bar.h -[E B C] +-bar.ooo -[E ] +-bar.c -[E ] +-bar.h -[E ] +-foo.h -""" - -test.run(arguments = "--debug=stree foo.xxx") -test.fail_test(string.find(test.stdout(), stree) == -1) - -stree2 = """ - E = exists - R = exists in repository only - b = implicit builder - B = explicit builder - S = side effect - P = precious - A = always build - C = current - -[ B ]+-foo.xxx -[ B ] +-foo.ooo -[E ] | +-foo.c -[E ] | +-foo.h -[E ] | +-bar.h -[ B ] +-bar.ooo -[E ] +-bar.c -[E ] +-bar.h -[E ] +-foo.h -""" - -test.run(arguments = '-c foo.xxx') -test.run(arguments = "--no-exec --debug=stree foo.xxx") -test.fail_test(string.find(test.stdout(), stree2) == -1) - - - -dtree = """ -+-foo.xxx - +-foo.ooo - +-bar.ooo -""" - -test.run(arguments = "--debug=dtree foo.xxx") -test.fail_test(string.find(test.stdout(), dtree) == -1) - -includes = """ -+-foo.c - +-foo.h - +-bar.h -""" -test.run(arguments = "--debug=includes foo.ooo") -test.fail_test(string.find(test.stdout(), includes) == -1) - -# Make sure we print the debug stuff even if there's a build failure. -test.write('bar.h', """ -#ifndef BAR_H -#define BAR_H -#include "foo.h" -#endif -THIS SHOULD CAUSE A BUILD FAILURE -""") - -test.run(arguments = "--debug=tree foo.xxx", - status = 2, - stderr = None) -test.fail_test(string.find(test.stdout(), tree) == -1) - -test.run(arguments = "--debug=dtree foo.xxx", - status = 2, - stderr = None) -test.fail_test(string.find(test.stdout(), dtree) == -1) - -# In an ideal world, --debug=includes would also work when there's a build -# failure, but this would require even more complicated logic to scan -# all of the intermediate nodes that get skipped when the build failure -# occurs. On the YAGNI theory, we're just not going to worry about this -# until it becomes an issue that someone actually cares enough about. -#test.run(arguments = "--debug=includes foo.xxx", -# status = 2, -# stderr = None) -#test.fail_test(string.find(test.stdout(), includes) == -1) - -# Restore bar.h to something good. -test.write('bar.h', """ -#ifndef BAR_H -#define BAR_H -#include "foo.h" -#endif -""") - -# These shouldn't print out anything in particular, but -# they shouldn't crash either: -test.run(arguments = "--debug=includes .") -test.run(arguments = "--debug=includes foo.c") - -tree = """scons: `.' is up to date. - -+-. - +-SConstruct - +-bar.c - +-bar.h - +-bar.ooo - | +-bar.c - | +-bar.h - | +-foo.h - +-foo.c - +-foo.h - +-foo.ooo - | +-foo.c - | +-foo.h - | +-bar.h - +-foo.xxx - +-foo.ooo - | +-foo.c - | +-foo.h - | +-bar.h - +-bar.ooo - +-bar.c - +-bar.h - +-foo.h -""" -test.run(arguments = "--debug=tree .") -test.fail_test(string.find(test.stdout(), tree) == -1) +############################ +# test --debug=time test.run(arguments = "--debug=pdb", stdin = "n\ns\nq\n") test.fail_test(string.find(test.stdout(), "(Pdb)") == -1) diff --git a/test/option/debug-dtree.py b/test/option/debug-dtree.py new file mode 100644 index 00000000..c93ff7f0 --- /dev/null +++ b/test/option/debug-dtree.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that the --debug=dtree option correctly prints just the explicit +dependencies (sources or Depends()) of a target. +""" + +import TestSCons +import sys +import string +import re +import time + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') +env.Program('foo', Split('foo.c bar.c')) +""") + +test.write('foo.c', r""" +#include "foo.h" +int main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("f1.c\n"); + exit (0); +} +""") + +test.write('bar.c', """ +#include "bar.h" +""") + +test.write('foo.h', """ +#ifndef FOO_H +#define FOO_H +#include "bar.h" +#endif +""") + +test.write('bar.h', """ +#ifndef BAR_H +#define BAR_H +#include "foo.h" +#endif +""") + +dtree1 = """ ++-foo.xxx + +-foo.ooo + +-bar.ooo +""" + +test.run(arguments = "--debug=dtree foo.xxx") +test.fail_test(string.find(test.stdout(), dtree1) == -1) + +dtree2 = """ ++-. + +-bar.ooo + +-foo.ooo + +-foo.xxx + +-foo.ooo + +-bar.ooo +""" +test.run(arguments = "--debug=dtree .") +test.fail_test(string.find(test.stdout(), dtree2) == -1) + +# Make sure we print the debug stuff even if there's a build failure. +test.write('bar.h', """ +#ifndef BAR_H +#define BAR_H +#include "foo.h" +#endif +THIS SHOULD CAUSE A BUILD FAILURE +""") + +test.run(arguments = "--debug=dtree foo.xxx", + status = 2, + stderr = None) +test.fail_test(string.find(test.stdout(), dtree1) == -1) + +test.pass_test() diff --git a/test/option/debug-includes.py b/test/option/debug-includes.py new file mode 100644 index 00000000..c2321758 --- /dev/null +++ b/test/option/debug-includes.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that the --debug=includes option prints the implicit +dependencies of a target. +""" + +import TestSCons +import sys +import string +import re +import time + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') +env.Program('foo', Split('foo.c bar.c')) +""") + +test.write('foo.c', r""" +#include "foo.h" +int main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("f1.c\n"); + exit (0); +} +""") + +test.write('bar.c', """ +#include "bar.h" +""") + +test.write('foo.h', """ +#ifndef FOO_H +#define FOO_H +#include "bar.h" +#endif +""") + +test.write('bar.h', """ +#ifndef BAR_H +#define BAR_H +#include "foo.h" +#endif +""") + +includes = """ ++-foo.c + +-foo.h + +-bar.h +""" +test.run(arguments = "--debug=includes foo.ooo") +test.fail_test(string.find(test.stdout(), includes) == -1) + +# In an ideal world, --debug=includes would also work when there's a build +# failure, but this would require even more complicated logic to scan +# all of the intermediate nodes that get skipped when the build failure +# occurs. On the YAGNI theory, we're just not going to worry about this +# until it becomes an issue that someone actually cares enough about. + +#test.write('bar.h', """ +##ifndef BAR_H +##define BAR_H +##include "foo.h" +##endif +#THIS SHOULD CAUSE A BUILD FAILURE +#""") + +#test.run(arguments = "--debug=includes foo.xxx", +# status = 2, +# stderr = None) +#test.fail_test(string.find(test.stdout(), includes) == -1) + +# These shouldn't print out anything in particular, but +# they shouldn't crash either: +test.run(arguments = "--debug=includes .") +test.run(arguments = "--debug=includes foo.c") + +test.pass_test() diff --git a/test/option/debug-stree.py b/test/option/debug-stree.py new file mode 100644 index 00000000..ba18cfbc --- /dev/null +++ b/test/option/debug-stree.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that the --debug=stree option prints a dependency tree with output +that indicates the state of various Node status flags. +""" + +import TestSCons +import sys +import string +import re +import time + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') +env.Program('foo', Split('foo.c bar.c')) +""") + +test.write('foo.c', r""" +#include "foo.h" +int main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("f1.c\n"); + exit (0); +} +""") + +test.write('bar.c', """ +#include "bar.h" +""") + +test.write('foo.h', """ +#ifndef FOO_H +#define FOO_H +#include "bar.h" +#endif +""") + +test.write('bar.h', """ +#ifndef BAR_H +#define BAR_H +#include "foo.h" +#endif +""") + +stree = """ +[E B C]+-foo.xxx +[E B C] +-foo.ooo +[E ] | +-foo.c +[E ] | +-foo.h +[E ] | +-bar.h +[E B C] +-bar.ooo +[E ] +-bar.c +[E ] +-bar.h +[E ] +-foo.h +""" + +test.run(arguments = "--debug=stree foo.xxx") +test.fail_test(string.find(test.stdout(), stree) == -1) + +stree2 = """ + E = exists + R = exists in repository only + b = implicit builder + B = explicit builder + S = side effect + P = precious + A = always build + C = current + +[ B ]+-foo.xxx +[ B ] +-foo.ooo +[E ] | +-foo.c +[E ] | +-foo.h +[E ] | +-bar.h +[ B ] +-bar.ooo +[E ] +-bar.c +[E ] +-bar.h +[E ] +-foo.h +""" + +test.run(arguments = '-c foo.xxx') + +test.run(arguments = "--no-exec --debug=stree foo.xxx") +test.fail_test(string.find(test.stdout(), stree2) == -1) + +test.pass_test() diff --git a/test/option/debug-tree.py b/test/option/debug-tree.py new file mode 100644 index 00000000..4bb1229d --- /dev/null +++ b/test/option/debug-tree.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test that the --debug=tree option prints a tree representation of the +complete dependencies of a target. +""" + +import TestSCons +import sys +import string +import re +import time + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx') +env.Program('foo', Split('foo.c bar.c')) +""") + +test.write('foo.c', r""" +#include "foo.h" +int main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf("f1.c\n"); + exit (0); +} +""") + +test.write('bar.c', """ +#include "bar.h" +""") + +test.write('foo.h', """ +#ifndef FOO_H +#define FOO_H +#include "bar.h" +#endif +""") + +test.write('bar.h', """ +#ifndef BAR_H +#define BAR_H +#include "foo.h" +#endif +""") + +tree1 = """ ++-foo.xxx + +-foo.ooo + | +-foo.c + | +-foo.h + | +-bar.h + +-bar.ooo + +-bar.c + +-bar.h + +-foo.h +""" + +test.run(arguments = "--debug=tree foo.xxx") +test.fail_test(string.find(test.stdout(), tree1) == -1) + +tree2 = """ ++-. + +-SConstruct + +-bar.c + +-bar.h + +-bar.ooo + | +-bar.c + | +-bar.h + | +-foo.h + +-foo.c + +-foo.h + +-foo.ooo + | +-foo.c + | +-foo.h + | +-bar.h + +-foo.xxx + +-foo.ooo + | +-foo.c + | +-foo.h + | +-bar.h + +-bar.ooo + +-bar.c + +-bar.h + +-foo.h +""" +test.run(arguments = "--debug=tree .") +test.fail_test(string.find(test.stdout(), tree2) == -1) + +# Make sure we print the debug stuff even if there's a build failure. +test.write('bar.h', """ +#ifndef BAR_H +#define BAR_H +#include "foo.h" +#endif +THIS SHOULD CAUSE A BUILD FAILURE +""") + +test.run(arguments = "--debug=tree foo.xxx", + status = 2, + stderr = None) +test.fail_test(string.find(test.stdout(), tree1) == -1) + +test.pass_test()