summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2006-12-16 01:43:01 (GMT)
committerSteven Knight <knight@baldmt.com>2006-12-16 01:43:01 (GMT)
commitc4d04b3b45e7b71a1b28053b90084bcf2fdf9c0e (patch)
tree8a0d07c078ac21bf1ab689eacf06577069bb9231 /test
parentb32cd624a5ad9526d28584b8e6c4a7958f436424 (diff)
downloadSCons-c4d04b3b45e7b71a1b28053b90084bcf2fdf9c0e.zip
SCons-c4d04b3b45e7b71a1b28053b90084bcf2fdf9c0e.tar.gz
SCons-c4d04b3b45e7b71a1b28053b90084bcf2fdf9c0e.tar.bz2
Merged revisions 1675-1736 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core ........ r1689 | stevenknight | 2006-11-06 20:56:29 -0600 (Mon, 06 Nov 2006) | 1 line 0.96.D483 - Merge changes for 0.96.93 packaging from the subsidiary branch. ........ r1690 | stevenknight | 2006-11-06 20:59:30 -0600 (Mon, 06 Nov 2006) | 1 line 0.96.D484 - Update HOWTO for releases. Fix name type in src/CHANGES.txt. ........ r1691 | stevenknight | 2006-11-08 13:55:36 -0600 (Wed, 08 Nov 2006) | 1 line 0.96.D485 - Fix MergeFlags() handling of None values. (John Pye) ........ r1692 | stevenknight | 2006-11-08 17:15:05 -0600 (Wed, 08 Nov 2006) | 1 line 0.96.D486 - Directly execute commands on Windows when possible. (Jay Kint) ........ r1693 | stevenknight | 2006-11-08 18:54:49 -0600 (Wed, 08 Nov 2006) | 1 line 0.96.D487 - Remove the semi-colon from the list of characters that determine when we use cmd ........ r1694 | stevenknight | 2006-11-09 01:34:06 -0600 (Thu, 09 Nov 2006) | 1 line 0.96.D488 - Pick up latex/bibtex 'Rerun to get citations correct' messages. (Dmitry Mikhin) ........ r1695 | stevenknight | 2006-11-11 08:36:33 -0600 (Sat, 11 Nov 2006) | 1 line 0.96.D489 - Back out the direct-execution-on-Windows change until we solve a corner case. ........ r1696 | stevenknight | 2006-11-15 10:33:10 -0600 (Wed, 15 Nov 2006) | 1 line 0.96.D490 - Fix the sconsign script when the .sconsign.dblite file is specified with its suf ........ r1697 | stevenknight | 2006-11-18 10:45:50 -0600 (Sat, 18 Nov 2006) | 4 lines Complete move of test/sconsign/script.py to underneath test/sconsign/script/. (This got left out of the previous checkin due to an error in the script that resubmits Aegis changes to Subversion.) ........ r1698 | stevenknight | 2006-11-18 11:05:26 -0600 (Sat, 18 Nov 2006) | 1 line 0.96.D491 - Allow an Options converter to take the construction environment as a parameter. ........ r1699 | stevenknight | 2006-11-30 15:34:37 -0600 (Thu, 30 Nov 2006) | 1 line 0.96.D492 - Reverse the order in which we try the arguments Options converters, first a sing ........ r1700 | stevenknight | 2006-11-30 16:03:09 -0600 (Thu, 30 Nov 2006) | 1 line 0.96.D493 - Speed up rel_path() by avoiding recomputation of intermediate directory relative ........ r1701 | stevenknight | 2006-11-30 16:14:16 -0600 (Thu, 30 Nov 2006) | 1 line 0.96.D494 - More efficient get_suffix(): compute it once when we set the name. ........ r1702 | stevenknight | 2006-11-30 16:22:55 -0600 (Thu, 30 Nov 2006) | 1 line 0.96.D495 - Fix missing XML end tags. ........ r1703 | stevenknight | 2006-11-30 17:15:25 -0600 (Thu, 30 Nov 2006) | 1 line 0.96.D496 - Turn Memoizer into a simple counter for --debug=memoizer, not something that doe ........ r1704 | stevenknight | 2006-11-30 20:30:50 -0600 (Thu, 30 Nov 2006) | 1 line 0.96.D497 - Add the scons-time script, with doc and tests. ........ r1705 | stevenknight | 2006-11-30 23:28:20 -0600 (Thu, 30 Nov 2006) | 1 line 0.96.D498 - Update the copyright years string. ........ r1706 | stevenknight | 2006-12-01 11:54:22 -0600 (Fri, 01 Dec 2006) | 1 line 0.96.D499 - Fix _do_Lookup => _doLookup value-caching misspellings. (Ben Leslie) ........ r1707 | stevenknight | 2006-12-01 12:03:46 -0600 (Fri, 01 Dec 2006) | 1 line 0.96.D500 - Fix copyright test against debian build. (Walter Franzini) ........ r1708 | stevenknight | 2006-12-01 14:23:29 -0600 (Fri, 01 Dec 2006) | 1 line 0.96.D501 - Add #include lines for test portability. (Gary Oberbrunner) ........ r1709 | stevenknight | 2006-12-01 14:51:12 -0600 (Fri, 01 Dec 2006) | 1 line 0.96.D502 - Fix tests under Python versions with no profiler (pstats module). ........ r1710 | stevenknight | 2006-12-01 20:04:49 -0600 (Fri, 01 Dec 2006) | 1 line 0.96.D503 - Remove unnecessary os.path.normpath() calls. (Gary Oberbrunner) ........ r1711 | stevenknight | 2006-12-01 20:34:31 -0600 (Fri, 01 Dec 2006) | 1 line 0.96.D504 - Accomodate arbitray white space after a SWIG %module keyword. (Anonymous) ........ r1712 | stevenknight | 2006-12-05 14:49:54 -0600 (Tue, 05 Dec 2006) | 1 line 0.96.D506 - Cache substitutions of of Builder source suffixes. Use a new PathList module, and a refactor Node.FS.Rfindalldirs() method, to cache calculations of values like CPPPATH. ........ r1713 | stevenknight | 2006-12-05 18:43:36 -0600 (Tue, 05 Dec 2006) | 1 line 0.96.D507 - Use cached stat() values in diskchecks. ........ r1714 | stevenknight | 2006-12-05 21:11:24 -0600 (Tue, 05 Dec 2006) | 1 line 0.96.D508 - Fix Memoizer hit counts for methods memoizing simple values. Clean up the code for memoizing return values in a dictionary. Fix comments. ........ r1715 | stevenknight | 2006-12-06 07:23:18 -0600 (Wed, 06 Dec 2006) | 1 line 0.96.D369 - More efficient Node.FS.Dir.current() check. Fix some Windows test portability issues. ........ r1716 | stevenknight | 2006-12-06 12:24:32 -0600 (Wed, 06 Dec 2006) | 2 lines Undo previous checkin (distributed incorrect Aegis change number). ........ r1717 | stevenknight | 2006-12-06 12:34:53 -0600 (Wed, 06 Dec 2006) | 1 line 0.96.D505 - Update ae-{cvs,svn}-ci for newer versions of aetar, and to not truncate descriptions. ........ r1718 | stevenknight | 2006-12-07 23:01:41 -0600 (Thu, 07 Dec 2006) | 1 line 0.96.D509 - Only look for mslink on Windows systems. (Sohail Somani) ........ r1719 | stevenknight | 2006-12-07 23:18:33 -0600 (Thu, 07 Dec 2006) | 1 line 0.96.D510 - Have the D compiler Tool use the same logic for shared libraries, too. (Paolo Invernizzi) ........ r1720 | stevenknight | 2006-12-07 23:29:47 -0600 (Thu, 07 Dec 2006) | 1 line 0.96.D511 - Generalize a JobTests.py test so it doesn't assume a specific order in which the operating system executes the threads. ........ r1721 | stevenknight | 2006-12-07 23:39:37 -0600 (Thu, 07 Dec 2006) | 1 line 0.96.D512 - Back out the Tool/dmd.py change; it breaks shared library linking for other lanuages beside D in the construction environment. ........ r1722 | stevenknight | 2006-12-07 23:47:11 -0600 (Thu, 07 Dec 2006) | 1 line 0.96.D513 - Test fixes: Windows portability, handle changes to Python 2.5 messages. ........ r1723 | stevenknight | 2006-12-08 00:00:13 -0600 (Fri, 08 Dec 2006) | 1 line 0.96.D514 - Change how the 'as' Tool is imported to accomodate the Python 2.6 'as' keyword. ........ r1724 | stevenknight | 2006-12-08 11:19:27 -0600 (Fri, 08 Dec 2006) | 1 line 0.96.D515 - Cache both Node.FS.find_file() and Node.FS.Dri.srcdir_find_file(). ........ r1725 | stevenknight | 2006-12-08 17:27:35 -0600 (Fri, 08 Dec 2006) | 1 line 0.96.D516 - Better error when we try to fetch contents from an Entry that doesn't exist. (Tom Parker) ........ r1726 | stevenknight | 2006-12-08 23:28:55 -0600 (Fri, 08 Dec 2006) | 1 line 0.96.D517 - Make sure we pick up the scons-local directory regardless of where we chdir internally. ........ r1727 | stevenknight | 2006-12-11 16:25:53 -0600 (Mon, 11 Dec 2006) | 1 line 0.96.D518 - Cache results of Executor.get_unignored_sources() and Executor.process_sources(). Eliminate some map() and disambiguate() calls when scanning for implicit dependencies. ........ r1728 | stevenknight | 2006-12-12 14:32:22 -0600 (Tue, 12 Dec 2006) | 1 line 0.96.D519 - Fix SideEffect() when -j is used. ........ r1729 | stevenknight | 2006-12-12 16:58:15 -0600 (Tue, 12 Dec 2006) | 1 line 0.96.D520 - Add a srcdir keyword to Builder calls. ........ r1730 | stevenknight | 2006-12-12 21:40:59 -0600 (Tue, 12 Dec 2006) | 1 line 0.96.D521 - TeX/LaTeX updates, including handling files in subdirectories. (Joel B. Mohler, Rob Managan, Dmitry Mikhin) ........ r1731 | stevenknight | 2006-12-14 15:01:02 -0600 (Thu, 14 Dec 2006) | 1 line 0.96.D522 - Propogate TypeErrors during variable substitution for display to the user. ........ r1732 | stevenknight | 2006-12-14 20:01:49 -0600 (Thu, 14 Dec 2006) | 1 line 0.96.D523 - Fix the os.path.join() calls in EnvironmentTests.py. ........ r1733 | stevenknight | 2006-12-15 07:48:22 -0600 (Fri, 15 Dec 2006) | 1 line 0.96.D524 - Fix source directories as dependencies of an Alias (0.96.93 problem found by LilyPond). ........ r1735 | stevenknight | 2006-12-15 12:43:45 -0600 (Fri, 15 Dec 2006) | 1 line 0.96.D525 - Allow printing Debug.caller() output (or other end-of-run debugging info) when using -h. ........ r1736 | stevenknight | 2006-12-15 16:30:08 -0600 (Fri, 15 Dec 2006) | 1 line 0.96.D526 - Add an option to debug IndexError and NameError exceptions during variable substitution. ........
Diffstat (limited to 'test')
-rw-r--r--test/Alias/srcdir.py100
-rw-r--r--test/BadBuilder.py11
-rw-r--r--test/BuildDir/errors.py3
-rw-r--r--test/Builder/srcdir.py76
-rw-r--r--test/Errors/AttributeError.py47
-rw-r--r--test/Errors/Exception.py83
-rw-r--r--test/Errors/InternalError.py53
-rw-r--r--test/Errors/NameError.py47
-rw-r--r--test/Errors/SyntaxError.py51
-rw-r--r--test/Errors/TypeError.py47
-rw-r--r--test/Errors/UserError.py50
-rw-r--r--test/Errors/exit-status.py54
-rw-r--r--test/Options/Options.py28
-rw-r--r--test/SConscript/src_dir.py2
-rw-r--r--test/SWIG/SWIG.py2
-rw-r--r--test/Scanner/generated.py2
-rw-r--r--test/SideEffect.py211
-rw-r--r--test/SideEffect/basic.py108
-rw-r--r--test/SideEffect/build_dir.py77
-rw-r--r--test/SideEffect/directory.py76
-rw-r--r--test/SideEffect/parallel.py126
-rw-r--r--test/Subst/AllowSubstExceptions.py93
-rw-r--r--test/Subst/SyntaxError.py74
-rw-r--r--test/Subst/TypeError.py92
-rw-r--r--test/TEX/TEX.py16
-rw-r--r--test/TEX/build_dir.py256
-rw-r--r--test/TEX/subdir-input.py80
-rw-r--r--test/errors.py224
-rw-r--r--test/import.py106
-rw-r--r--test/option-c.py21
-rw-r--r--test/option-v.py29
-rw-r--r--test/option/debug-memoizer.py80
-rw-r--r--test/option/debug-nomemoizer.py34
-rw-r--r--test/option/profile.py6
-rw-r--r--test/scons-time/func/basic.py49
-rw-r--r--test/scons-time/func/chdir.py64
-rw-r--r--test/scons-time/func/file.py80
-rw-r--r--test/scons-time/func/format-gnuplot.py82
-rw-r--r--test/scons-time/func/function.py58
-rw-r--r--test/scons-time/func/glob.py57
-rw-r--r--test/scons-time/func/help.py57
-rw-r--r--test/scons-time/func/no-args.py43
-rw-r--r--test/scons-time/func/prefix.py65
-rw-r--r--test/scons-time/func/tail.py56
-rw-r--r--test/scons-time/help/all-subcommands.py58
-rw-r--r--test/scons-time/help/options.py59
-rw-r--r--test/scons-time/mem/chdir.py57
-rw-r--r--test/scons-time/mem/file.py71
-rw-r--r--test/scons-time/mem/format-gnuplot.py72
-rw-r--r--test/scons-time/mem/glob.py52
-rw-r--r--test/scons-time/mem/help.py57
-rw-r--r--test/scons-time/mem/no-args.py43
-rw-r--r--test/scons-time/mem/prefix.py62
-rw-r--r--test/scons-time/mem/stage.py83
-rw-r--r--test/scons-time/mem/tail.py55
-rw-r--r--test/scons-time/no-args.py42
-rw-r--r--test/scons-time/obj/chdir.py57
-rw-r--r--test/scons-time/obj/file.py71
-rw-r--r--test/scons-time/obj/format-gnuplot.py76
-rw-r--r--test/scons-time/obj/glob.py52
-rw-r--r--test/scons-time/obj/help.py57
-rw-r--r--test/scons-time/obj/no-args.py42
-rw-r--r--test/scons-time/obj/no-files.py44
-rw-r--r--test/scons-time/obj/prefix.py62
-rw-r--r--test/scons-time/obj/stage.py88
-rw-r--r--test/scons-time/obj/tail.py55
-rw-r--r--test/scons-time/run/aegis.py84
-rw-r--r--test/scons-time/run/archive/dir.py49
-rw-r--r--test/scons-time/run/archive/tar-gz.py49
-rw-r--r--test/scons-time/run/archive/tar.py49
-rw-r--r--test/scons-time/run/archive/tgz.py49
-rw-r--r--test/scons-time/run/archive/zip.py49
-rw-r--r--test/scons-time/run/config/archive_list.py73
-rw-r--r--test/scons-time/run/config/initial_commands.py56
-rw-r--r--test/scons-time/run/config/prefix.py52
-rw-r--r--test/scons-time/run/config/python.py68
-rw-r--r--test/scons-time/run/config/scons.py65
-rw-r--r--test/scons-time/run/config/subdir.py63
-rw-r--r--test/scons-time/run/config/targets.py86
-rw-r--r--test/scons-time/run/option/help.py59
-rw-r--r--test/scons-time/run/option/next-run.py99
-rw-r--r--test/scons-time/run/option/no-args.py42
-rw-r--r--test/scons-time/run/option/no-exec.py49
-rw-r--r--test/scons-time/run/option/number.py48
-rw-r--r--test/scons-time/run/option/outdir.py51
-rw-r--r--test/scons-time/run/option/prefix.py48
-rw-r--r--test/scons-time/run/option/python.py64
-rw-r--r--test/scons-time/run/option/quiet.py96
-rw-r--r--test/scons-time/run/option/scons.py59
-rw-r--r--test/scons-time/run/option/subdir.py59
-rw-r--r--test/scons-time/run/option/verbose.py161
-rw-r--r--test/scons-time/run/subversion.py85
-rw-r--r--test/scons-time/time/chdir.py57
-rw-r--r--test/scons-time/time/file.py71
-rw-r--r--test/scons-time/time/format-gnuplot.py72
-rw-r--r--test/scons-time/time/glob.py52
-rw-r--r--test/scons-time/time/help.py57
-rw-r--r--test/scons-time/time/no-args.py43
-rw-r--r--test/scons-time/time/prefix.py62
-rw-r--r--test/scons-time/time/tail.py55
-rw-r--r--test/scons-time/time/which.py84
-rw-r--r--test/scons-time/unknown.py45
-rw-r--r--test/sconsign/script.py602
-rw-r--r--test/sconsign/script/SConsignFile.py260
-rw-r--r--test/sconsign/script/Signatures.py109
-rw-r--r--test/sconsign/script/bad.py61
-rw-r--r--test/sconsign/script/dblite.py122
-rw-r--r--test/sconsign/script/no-SConsignFile.py205
-rw-r--r--test/symlink/BuildDir.py4
109 files changed, 6801 insertions, 1163 deletions
diff --git a/test/Alias/srcdir.py b/test/Alias/srcdir.py
new file mode 100644
index 0000000..2251165
--- /dev/null
+++ b/test/Alias/srcdir.py
@@ -0,0 +1,100 @@
+#!/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__"
+
+"""
+Verify that an Alias for a BuildDir()'s source directory works as
+expected.
+
+This tests for a 0.96.93 bug uncovered by the LilyPond project's build.
+
+The specific problem is that, in 0.96.93, the simple act of trying to
+disambiguate a target file in the BuildDir() would call srcnode(), which
+would create a "phantom" Node for the target in the *source* directory:
+
+ +-minimal
+ +-python
+ +-foo <= this doesn't belong!
+ +-foo.py
+ +-out-scons
+ +-foo <= this is all right
+ +-foo.py
+
+As part of deciding if the 'minimal' Alias is up-to-date, the 'python'
+source directory would get scanned for files, including the "phantom"
+'python/foo' target Node. Since this didn't exist, the build would die:
+
+ scons: *** Source `python/foo' not found, needed by target `minimal'. Stop.
+
+The specific 0.96.94 solution was to make the Node.FS.Entry.disambiguate()
+smarter about looking on disk. Future versions may solve this in other
+ways as the architecture evolves, of course, but this will still make
+for good test case regardless.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('python')
+
+test.write('SConstruct', """\
+import os.path
+
+env = Environment ()
+
+def at_copy_ext (target, source, env):
+ n = str (source[0])
+ s = open (n, 'rb').read ()
+ e = os.path.splitext (n)[1]
+ t = str (target[0]) + e
+ open (t, 'wb').write (s)
+
+AT_COPY_EXT = Builder (action = at_copy_ext, src_suffix=['.py', '.sh',])
+env.Append (BUILDERS = {'AT_COPY_EXT': AT_COPY_EXT})
+
+env.Alias ('minimal', ['python'])
+
+Export ('env')
+
+b = 'python/out-scons'
+
+env.BuildDir(b, 'python', duplicate=0)
+
+SConscript(b + '/SConscript')
+""")
+
+test.write(['python', 'SConscript'], """\
+Import ('env')
+env.AT_COPY_EXT('foo.py')
+""")
+
+test.write(['python', 'foo.py'], 'python/foo.py\n')
+
+test.run('minimal')
+
+test.must_match(['python', 'out-scons', 'foo.py'], "python/foo.py\n")
+
+test.pass_test()
diff --git a/test/BadBuilder.py b/test/BadBuilder.py
index 8c28ea5..c7c9c95 100644
--- a/test/BadBuilder.py
+++ b/test/BadBuilder.py
@@ -58,6 +58,8 @@ foo.b
built
""")
+python_file_line = test.python_file_line(SConstruct_path, 14)
+
### Gross mistake in Builder spec
test.write(SConstruct_path, sconstruct % '\
@@ -66,8 +68,7 @@ b2 = Builder(act__ion=buildop, src_suffix=".b", suffix=".c")')
expect_stderr = """\
scons: *** Builder b2 must have an action to build ['foo.c'].
-File "%(SConstruct_path)s", line 14, in ?
-""" % locals()
+""" + python_file_line
test.run(arguments='.', stderr=expect_stderr, status = 2)
@@ -79,8 +80,7 @@ b2 = Builder(actoin=buildop, src_suffix=".b", suffix=".c")')
expect_stderr="""\
scons: *** Builder b2 must have an action to build ['foo.c'].
-File "%(SConstruct_path)s", line 14, in ?
-""" % locals()
+""" + python_file_line
test.run(arguments='test2', stderr=expect_stderr, status=2)
@@ -92,8 +92,7 @@ b2 = Builder(src_suffix=".b", suffix=".c")')
expect_stderr = """\
scons: *** Builder b2 must have an action to build ['foo.c'].
-File "%(SConstruct_path)s", line 14, in ?
-""" % locals()
+""" + python_file_line
test.run(arguments='test2', stderr=expect_stderr, status = 2)
diff --git a/test/BuildDir/errors.py b/test/BuildDir/errors.py
index 4fcd625..44096a1 100644
--- a/test/BuildDir/errors.py
+++ b/test/BuildDir/errors.py
@@ -165,8 +165,7 @@ BuildDir('build', 'src2')
expect_stderr = """
scons: *** 'build' already has a source directory: 'src1'.
-File "%(duplicate_SConstruct_path)s", line 2, in ?
-""" % locals()
+""" + test.python_file_line(duplicate_SConstruct_path, 2)
test.run(chdir = 'duplicate',
arguments = ".",
diff --git a/test/Builder/srcdir.py b/test/Builder/srcdir.py
new file mode 100644
index 0000000..4f378a7
--- /dev/null
+++ b/test/Builder/srcdir.py
@@ -0,0 +1,76 @@
+#!/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__"
+
+"""
+Verify that specifying a srcdir when calling a Builder correctly
+prefixes each relative-path string with the specified srcdir.
+"""
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+test.subdir('src', ['src', 'foo'])
+
+file3 = test.workpath('file3')
+
+test.write(['src', 'cat.py'], """\
+import sys
+o = open(sys.argv[1], 'wb')
+for f in sys.argv[2:]:
+ o.write(open(f, 'rb').read())
+o.close()
+""")
+
+test.write(['src', 'SConstruct'], """\
+Command('output',
+ ['file1', File('file2'), r'%(file3)s', 'file4'],
+ '%(_python_)s cat.py $TARGET $SOURCES',
+ srcdir='foo')
+""" % locals())
+
+test.write(['src', 'foo', 'file1'], "file1\n")
+
+test.write(['src', 'file2'], "file2\n")
+
+test.write(file3, "file3\n")
+
+test.write(['src', 'foo', 'file4'], "file4\n")
+
+test.run(chdir = 'src', arguments = '.')
+
+expected = """\
+file1
+file2
+file3
+file4
+"""
+
+test.must_match(['src', 'output'], expected)
+
+test.pass_test()
diff --git a/test/Errors/AttributeError.py b/test/Errors/AttributeError.py
new file mode 100644
index 0000000..637cccf
--- /dev/null
+++ b/test/Errors/AttributeError.py
@@ -0,0 +1,47 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if an SConstruct file
+throws an AttributeError.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+a = 1
+a.append(2)
+""")
+
+test.run(status = 2, stderr = """\
+(AttributeError|<type 'exceptions\.AttributeError'>): 'int' object has no attribute 'append':
+ File ".+SConstruct", line 2:
+ a.append\(2\)
+""")
+
+test.pass_test()
diff --git a/test/Errors/Exception.py b/test/Errors/Exception.py
new file mode 100644
index 0000000..710c819
--- /dev/null
+++ b/test/Errors/Exception.py
@@ -0,0 +1,83 @@
+#!/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__"
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+def foo(env, target, source):
+ print str(target[0])
+ open(str(target[0]), 'wt').write('foo')
+
+def exit(env, target, source):
+ raise Exception('exit')
+
+env = Environment(BUILDERS = { 'foo' : Builder(action=foo),
+ 'exit' : Builder(action=exit) })
+
+env.foo('foo.out', 'foo.in')
+env.exit('exit.out', 'exit.in')
+""")
+
+test.write('foo.in', 'foo\n')
+
+test.write('exit.in', 'exit\n')
+
+# print_exception doesn't always show a source line if the source file
+# no longer exists or that line in the source file no longer exists,
+# so make sure the proper variations are supported in the following
+# regexp.
+expect = """scons: \*\*\* \[exit.out\] Exception
+Traceback \((most recent call|innermost) last\):
+( File ".+", line \d+, in \S+
+ [^\n]+
+)*( File ".+", line \d+, in \S+
+)*( File ".+", line \d+, in \S+
+ [^\n]+
+)*\S.+
+"""
+
+# Build foo.out first, and expect an error when we try to build exit.out.
+test.run(arguments='foo.out exit.out', stderr=expect, status=2)
+
+# Rebuild. foo.out should be up to date, and we should get the
+# expected error building exit.out.
+test.run(arguments='foo.out exit.out', stderr=expect, status=2)
+
+stdout = test.stdout()
+
+expect = "scons: `foo.out' is up to date."
+
+if string.find(stdout, expect) == -1:
+ print "Did not find expected string %s" % repr(expect)
+ print "STDOUT ======================================================="
+ print stdout
+ test.fail_test()
+
+test.pass_test()
diff --git a/test/Errors/InternalError.py b/test/Errors/InternalError.py
new file mode 100644
index 0000000..e90d402
--- /dev/null
+++ b/test/Errors/InternalError.py
@@ -0,0 +1,53 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if an SConstruct file
+throws an InternalError.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+# Test InternalError.
+test.write('SConstruct', """
+assert not globals().has_key("InternalError")
+from SCons.Errors import InternalError
+raise InternalError, 'error inside'
+""")
+
+test.run(stdout = "scons: Reading SConscript files ...\ninternal error\n",
+ stderr = r"""Traceback \((most recent call|innermost) last\):
+ File ".+", line \d+, in .+
+ File ".+", line \d+, in .+
+ File ".+", line \d+, in .+
+ File ".+SConstruct", line \d+, in .+
+ raise InternalError, 'error inside'
+InternalError: error inside
+""", status=2)
+
+test.pass_test()
diff --git a/test/Errors/NameError.py b/test/Errors/NameError.py
new file mode 100644
index 0000000..be69b50
--- /dev/null
+++ b/test/Errors/NameError.py
@@ -0,0 +1,47 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if an SConstruct file
+throws a NameError (tries to reference a Python variable that
+doesn't exist).
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+a == 1
+""")
+
+test.run(status = 2, stderr = """\
+NameError: [^\n]*
+ File ".+SConstruct", line 1:
+ a == 1
+""")
+
+test.pass_test()
diff --git a/test/Errors/SyntaxError.py b/test/Errors/SyntaxError.py
new file mode 100644
index 0000000..b9ff1ff
--- /dev/null
+++ b/test/Errors/SyntaxError.py
@@ -0,0 +1,51 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if an SConstruct file
+throws a SyntaxError (contains improper Python code).
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """
+a ! x
+""")
+
+test.run(stdout = "scons: Reading SConscript files ...\n",
+ stderr = """ File ".+SConstruct", line 2
+
+ a ! x
+
+ \^
+
+SyntaxError: invalid syntax
+
+""", status=2)
+
+test.pass_test()
diff --git a/test/Errors/TypeError.py b/test/Errors/TypeError.py
new file mode 100644
index 0000000..1ec14dd
--- /dev/null
+++ b/test/Errors/TypeError.py
@@ -0,0 +1,47 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if an SConstruct file
+throws a TypeError.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+a = 1
+a[2] = 3
+""")
+
+test.run(status = 2, stderr = """\
+TypeError:( 'int')? object does not support item assignment:
+ File ".+SConstruct", line 2:
+ a\[2\] = 3
+""")
+
+test.pass_test()
diff --git a/test/Errors/UserError.py b/test/Errors/UserError.py
new file mode 100644
index 0000000..69ed7d4
--- /dev/null
+++ b/test/Errors/UserError.py
@@ -0,0 +1,50 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if an SConstruct file
+throws a UserError.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """
+assert not globals().has_key("UserError")
+import SCons.Errors
+raise SCons.Errors.UserError, 'Depends() requires both sources and targets.'
+""")
+
+expect = """
+scons: \*\*\* Depends\(\) requires both sources and targets.
+""" + TestSCons.file_expr
+
+test.run(stdout = "scons: Reading SConscript files ...\n",
+ stderr = expect,
+ status=2)
+
+test.pass_test()
diff --git a/test/Errors/exit-status.py b/test/Errors/exit-status.py
new file mode 100644
index 0000000..946c1c4
--- /dev/null
+++ b/test/Errors/exit-status.py
@@ -0,0 +1,54 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if an external command throws
+a non-zero exit status.
+"""
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('build.py', '''
+import sys
+sys.exit(7)
+''')
+
+test.write('SConstruct', """
+env=Environment()
+Default(env.Command(['one.out', 'two.out'],
+ ['foo.in'],
+ action=r'%(_python_)s build.py'))
+""" % locals())
+
+test.write('foo.in', "foo.in\n")
+
+test.run(status=2, stderr="scons: \\*\\*\\* \\[one.out\\] Error 7\n")
+
+test.pass_test()
diff --git a/test/Options/Options.py b/test/Options/Options.py
index bd827d1..11452b1 100644
--- a/test/Options/Options.py
+++ b/test/Options/Options.py
@@ -47,6 +47,14 @@ def validator(key, value, environ):
environ[key] = "v"
environ["valid_key"] = "v"
+
+def old_converter (value):
+ return "old_converter"
+
+def new_converter (value, env):
+ return "new_converter"
+
+
opts = Options('custom.py')
opts.Add('RELEASE_BUILD',
'Set to 1 to build a release build',
@@ -69,6 +77,18 @@ opts.Add('VALIDATE',
validator,
None)
+opts.Add('OLD_CONVERTER',
+ 'An option for testing converters that take one parameter',
+ "foo",
+ None,
+ old_converter)
+
+opts.Add('NEW_CONVERTER',
+ 'An option for testing converters that take two parameters',
+ "foo",
+ None,
+ new_converter)
+
opts.Add('UNSPECIFIED',
'An option with no value')
@@ -168,6 +188,14 @@ VALIDATE: An option for testing validation
default: notset
actual: v
+OLD_CONVERTER: An option for testing converters that take one parameter
+ default: foo
+ actual: old_converter
+
+NEW_CONVERTER: An option for testing converters that take two parameters
+ default: foo
+ actual: new_converter
+
UNSPECIFIED: An option with no value
default: None
actual: None
diff --git a/test/SConscript/src_dir.py b/test/SConscript/src_dir.py
index f18066b..aaf3bcb 100644
--- a/test/SConscript/src_dir.py
+++ b/test/SConscript/src_dir.py
@@ -67,6 +67,7 @@ for source in sources:
test.write(['samples', 'goodbye.c'], """\
#include <stdio.h>
+#include <stdlib.h>
int main(int argc, char *argv[])
{
@@ -77,6 +78,7 @@ int main(int argc, char *argv[])
test.write(['src', 'hello.c'], """\
#include <stdio.h>
+#include <stdlib.h>
int main(int argc, char *argv[])
{
diff --git a/test/SWIG/SWIG.py b/test/SWIG/SWIG.py
index ed995a9..791d0e0 100644
--- a/test/SWIG/SWIG.py
+++ b/test/SWIG/SWIG.py
@@ -182,7 +182,7 @@ bar_string()
""")
test.write("bar.i", """\
-%module bar
+%module \t bar
%{
/* Put header files here (optional) */
%}
diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py
index a88303f..99b5787 100644
--- a/test/Scanner/generated.py
+++ b/test/Scanner/generated.py
@@ -28,7 +28,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify that we only scan generated .h files once.
This originated as a real-life bug report submitted by Scott Lystig
-Fritchie. It's been left as-is, rather than stripped down to bear
+Fritchie. It's been left as-is, rather than stripped down to bare
minimum, partly because it wasn't completely clear what combination of
factors triggered the bug Scott saw, and partly because the real-world
complexity is valuable in its own right.
diff --git a/test/SideEffect.py b/test/SideEffect.py
deleted file mode 100644
index f7533b5..0000000
--- a/test/SideEffect.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/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__"
-
-import os.path
-import string
-
-import TestSCons
-
-test = TestSCons.TestSCons()
-
-test.write('SConstruct', """\
-def copy(source, target):
- open(target, "wb").write(open(source, "rb").read())
-
-def build(env, source, target):
- copy(str(source[0]), str(target[0]))
- if target[0].side_effects:
- side_effect = open(str(target[0].side_effects[0]), "ab")
- side_effect.write('%%s -> %%s\\n'%%(str(source[0]), str(target[0])))
-
-Build = Builder(action=build)
-env = Environment(BUILDERS={'Build':Build}, SUBDIR='subdir')
-env.Build('foo.out', 'foo.in')
-env.Build('bar.out', 'bar.in')
-env.Build('blat.out', 'blat.in')
-SideEffect('log.txt', ['foo.out', 'bar.out', 'blat.out'])
-env.Build('log.out', 'log.txt')
-env.Build('subdir/baz.out', 'baz.in')
-env.SideEffect(r'%s', ['blat.out', r'%s'])
-env.Build('subdir/out.out', 'subdir/out.txt')
-""" % (os.path.join('$SUBDIR', 'out.txt'),
- os.path.join('$SUBDIR', 'baz.out')))
-
-test.write('foo.in', 'foo.in\n')
-test.write('bar.in', 'bar.in\n')
-test.write('blat.in', 'blat.in\n')
-test.write('baz.in', 'baz.in\n')
-
-test.run(arguments = 'foo.out bar.out', stdout=test.wrap_stdout("""\
-build(["foo.out"], ["foo.in"])
-build(["bar.out"], ["bar.in"])
-"""))
-
-expect = """\
-foo.in -> foo.out
-bar.in -> bar.out
-"""
-assert test.read('log.txt') == expect
-
-test.write('bar.in', 'bar.in 2 \n')
-
-test.run(arguments = 'log.txt', stdout=test.wrap_stdout("""\
-build(["bar.out"], ["bar.in"])
-build(["blat.out"], ["blat.in"])
-"""))
-
-expect = """\
-foo.in -> foo.out
-bar.in -> bar.out
-bar.in -> bar.out
-blat.in -> blat.out
-"""
-assert test.read('log.txt') == expect
-
-test.write('foo.in', 'foo.in 2 \n')
-
-test.run(arguments = ".", stdout=test.wrap_stdout("""\
-build(["foo.out"], ["foo.in"])
-build(["log.out"], ["log.txt"])
-build(["%s"], ["baz.in"])
-build(["%s"], ["%s"])
-""" % (os.path.join('subdir', 'baz.out'),
- os.path.join('subdir', 'out.out'),
- os.path.join('subdir', 'out.txt'))))
-
-expect = """\
-foo.in -> foo.out
-bar.in -> bar.out
-bar.in -> bar.out
-blat.in -> blat.out
-foo.in -> foo.out
-"""
-assert test.read('log.txt') == expect
-
-test.run(arguments = "-c .")
-
-test.must_not_exist(test.workpath('foo.out'))
-test.must_not_exist(test.workpath('bar.out'))
-test.must_not_exist(test.workpath('blat.out'))
-test.must_not_exist(test.workpath('log.txt'))
-
-build_lines = [
- 'build(["bar.out"], ["bar.in"])',
- 'build(["blat.out"], ["blat.in"])',
- 'build(["foo.out"], ["foo.in"])',
- 'build(["log.out"], ["log.txt"])',
- 'build(["%s"], ["baz.in"])' % os.path.join('subdir', 'baz.out'),
- 'build(["%s"], ["%s"])' % (os.path.join('subdir', 'out.out'),
- os.path.join('subdir', 'out.txt')),
-]
-test.run(arguments = "-j 4 .")
-output = test.stdout()
-for line in build_lines:
- test.fail_test(string.find(output, line) == -1)
-
-log_lines = [
- 'bar.in -> bar.out',
- 'blat.in -> blat.out',
- 'foo.in -> foo.out',
-]
-log = test.read('log.txt')
-for line in log_lines:
- test.fail_test(string.find(log, line) == -1)
-
-test.write('SConstruct',
-"""
-import os.path
-import os
-
-def copy(source, target):
- open(target, "wb").write(open(source, "rb").read())
-
-def build(env, source, target):
- copy(str(source[0]), str(target[0]))
- if target[0].side_effects:
- try: os.mkdir('log')
- except: pass
- copy(str(target[0]), os.path.join('log', str(target[0])))
-
-Build = Builder(action=build)
-env = Environment(BUILDERS={'Build':Build})
-env.Build('foo.out', 'foo.in')
-env.Build('bar.out', 'bar.in')
-env.Build('blat.out', 'blat.in')
-env.SideEffect(Dir('log'), ['foo.out', 'bar.out', 'blat.out'])
-""")
-
-test.run(arguments='foo.out')
-
-test.must_exist(test.workpath('foo.out'))
-test.must_exist(test.workpath('log/foo.out'))
-test.must_not_exist(test.workpath('log', 'bar.out'))
-test.must_not_exist(test.workpath('log', 'blat.out'))
-
-test.run(arguments='log')
-test.must_exist(test.workpath('log', 'bar.out'))
-test.must_exist(test.workpath('log', 'blat.out'))
-
-test.write('SConstruct',
-"""
-def copy(source, target):
- open(target, "wb").write(open(source, "rb").read())
-
-def build(env, source, target):
- copy(str(source[0]), str(target[0]))
- if target[0].side_effects:
- side_effect = open(str(target[0].side_effects[0]), "ab")
- side_effect.write('%s -> %s\\n'%(str(source[0]), str(target[0])))
-
-Build = Builder(action=build)
-env = Environment(BUILDERS={'Build':Build})
-Export('env')
-SConscript('SConscript', build_dir='build', duplicate=0)""")
-
-test.write('SConscript', """
-Import('env')
-env.Build('foo.out', 'foo.in')
-env.Build('bar.out', 'bar.in')
-env.Build('blat.out', 'blat.in')
-env.SideEffect('log.txt', ['foo.out', 'bar.out', 'blat.out'])
-""")
-
-test.write('foo.in', 'foo.in\n')
-test.write('bar.in', 'bar.in\n')
-
-build_foo_out = os.path.join('build', 'foo.out')
-build_bar_out = os.path.join('build', 'bar.out')
-
-test.run(arguments = '%s %s' % (build_foo_out, build_bar_out))
-
-expect = """\
-foo.in -> %s
-bar.in -> %s
-""" % (build_foo_out, build_bar_out)
-
-assert test.read('build/log.txt') == expect
-
-test.pass_test()
diff --git a/test/SideEffect/basic.py b/test/SideEffect/basic.py
new file mode 100644
index 0000000..b01020b
--- /dev/null
+++ b/test/SideEffect/basic.py
@@ -0,0 +1,108 @@
+#!/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__"
+
+"""
+Verify basic operation of the SideEffect() method, using a "log
+file" as the side effect "target."
+"""
+
+import os.path
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+def copy(source, target):
+ open(target, "wb").write(open(source, "rb").read())
+
+def build(env, source, target):
+ copy(str(source[0]), str(target[0]))
+ if target[0].side_effects:
+ side_effect = open(str(target[0].side_effects[0]), "ab")
+ side_effect.write('%%s -> %%s\\n'%%(str(source[0]), str(target[0])))
+
+Build = Builder(action=build)
+env = Environment(BUILDERS={'Build':Build}, SUBDIR='subdir')
+env.Build('foo.out', 'foo.in')
+env.Build('bar.out', 'bar.in')
+env.Build('blat.out', 'blat.in')
+SideEffect('log.txt', ['foo.out', 'bar.out', 'blat.out'])
+env.Build('log.out', 'log.txt')
+env.Build('subdir/baz.out', 'baz.in')
+env.SideEffect(r'%s', ['blat.out', r'%s'])
+env.Build('subdir/out.out', 'subdir/out.txt')
+""" % (os.path.join('$SUBDIR', 'out.txt'),
+ os.path.join('$SUBDIR', 'baz.out')))
+
+test.write('foo.in', 'foo.in\n')
+test.write('bar.in', 'bar.in\n')
+test.write('blat.in', 'blat.in\n')
+test.write('baz.in', 'baz.in\n')
+
+test.run(arguments = 'foo.out bar.out', stdout=test.wrap_stdout("""\
+build(["foo.out"], ["foo.in"])
+build(["bar.out"], ["bar.in"])
+"""))
+
+expect = """\
+foo.in -> foo.out
+bar.in -> bar.out
+"""
+test.must_match('log.txt', expect)
+
+test.write('bar.in', 'bar.in 2 \n')
+
+test.run(arguments = 'log.txt', stdout=test.wrap_stdout("""\
+build(["bar.out"], ["bar.in"])
+build(["blat.out"], ["blat.in"])
+"""))
+
+expect = expect + """\
+bar.in -> bar.out
+blat.in -> blat.out
+"""
+test.must_match('log.txt', expect)
+
+test.write('foo.in', 'foo.in 2 \n')
+
+test.run(arguments = ".", stdout=test.wrap_stdout("""\
+build(["foo.out"], ["foo.in"])
+build(["log.out"], ["log.txt"])
+build(["%s"], ["baz.in"])
+build(["%s"], ["%s"])
+""" % (os.path.join('subdir', 'baz.out'),
+ os.path.join('subdir', 'out.out'),
+ os.path.join('subdir', 'out.txt'))))
+
+expect = expect + """\
+foo.in -> foo.out
+"""
+
+test.must_match('log.txt', expect)
+
+test.pass_test()
diff --git a/test/SideEffect/build_dir.py b/test/SideEffect/build_dir.py
new file mode 100644
index 0000000..d33e3d4
--- /dev/null
+++ b/test/SideEffect/build_dir.py
@@ -0,0 +1,77 @@
+#!/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__"
+
+"""
+Verify correct operation of SideEffect() when an SConscript()
+build_dir is used.
+"""
+
+import os.path
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct',
+"""
+def copy(source, target):
+ open(target, "wb").write(open(source, "rb").read())
+
+def build(env, source, target):
+ copy(str(source[0]), str(target[0]))
+ if target[0].side_effects:
+ side_effect = open(str(target[0].side_effects[0]), "ab")
+ side_effect.write('%s -> %s\\n'%(str(source[0]), str(target[0])))
+
+Build = Builder(action=build)
+env = Environment(BUILDERS={'Build':Build})
+Export('env')
+SConscript('SConscript', build_dir='build', duplicate=0)""")
+
+test.write('SConscript', """
+Import('env')
+env.Build('foo.out', 'foo.in')
+env.Build('bar.out', 'bar.in')
+env.Build('blat.out', 'blat.in')
+env.SideEffect('log.txt', ['foo.out', 'bar.out', 'blat.out'])
+""")
+
+test.write('foo.in', 'foo.in\n')
+test.write('bar.in', 'bar.in\n')
+
+build_foo_out = os.path.join('build', 'foo.out')
+build_bar_out = os.path.join('build', 'bar.out')
+
+test.run(arguments = '%s %s' % (build_foo_out, build_bar_out))
+
+expect = """\
+foo.in -> %s
+bar.in -> %s
+""" % (build_foo_out, build_bar_out)
+
+test.must_match('build/log.txt', expect)
+
+test.pass_test()
diff --git a/test/SideEffect/directory.py b/test/SideEffect/directory.py
new file mode 100644
index 0000000..5ede853
--- /dev/null
+++ b/test/SideEffect/directory.py
@@ -0,0 +1,76 @@
+#!/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__"
+
+"""
+Verify that a directory (Dir()) works as a SideEffect() "target."
+"""
+
+import os.path
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import os.path
+import os
+
+def copy(source, target):
+ open(target, "wb").write(open(source, "rb").read())
+
+def build(env, source, target):
+ copy(str(source[0]), str(target[0]))
+ if target[0].side_effects:
+ try: os.mkdir('log')
+ except: pass
+ copy(str(target[0]), os.path.join('log', str(target[0])))
+
+Build = Builder(action=build)
+env = Environment(BUILDERS={'Build':Build})
+env.Build('foo.out', 'foo.in')
+env.Build('bar.out', 'bar.in')
+env.Build('blat.out', 'blat.in')
+env.SideEffect(Dir('log'), ['foo.out', 'bar.out', 'blat.out'])
+""")
+
+test.write('foo.in', "foo.in\n")
+test.write('bar.in', "bar.in\n")
+test.write('blat.in', "blat.in\n")
+
+test.run(arguments='foo.out')
+
+test.must_exist(test.workpath('foo.out'))
+test.must_exist(test.workpath('log/foo.out'))
+test.must_not_exist(test.workpath('log', 'bar.out'))
+test.must_not_exist(test.workpath('log', 'blat.out'))
+
+test.run(arguments='log')
+
+test.must_exist(test.workpath('log', 'bar.out'))
+test.must_exist(test.workpath('log', 'blat.out'))
+
+test.pass_test()
diff --git a/test/SideEffect/parallel.py b/test/SideEffect/parallel.py
new file mode 100644
index 0000000..7c9bc27
--- /dev/null
+++ b/test/SideEffect/parallel.py
@@ -0,0 +1,126 @@
+#!/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__"
+
+"""
+Verify that targets with the same SideEffect are not built in parallel
+when the -j option is used.
+"""
+
+import string
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+test.write('build.py', """\
+import os
+import sys
+import time
+
+lockdir = 'build.lock'
+logfile = 'log.txt'
+
+try:
+ os.mkdir(lockdir)
+except OSError, e:
+ msg = 'could not create lock directory: %s\\n' % e
+ sys.stderr.write(msg)
+ sys.exit(1)
+
+src, target = sys.argv[1:]
+
+open(logfile, 'ab').write('%s -> %s\\n' % (src, target))
+
+# Give the other threads a chance to start.
+time.sleep(1)
+
+os.rmdir(lockdir)
+""")
+
+test.write('SConstruct', """\
+Build = Builder(action=r'%(_python_)s build.py $SOURCE $TARGET')
+env = Environment(BUILDERS={'Build':Build})
+env.Build('h1.out', 'h1.in')
+env.Build('g2.out', 'g2.in')
+env.Build('f3.out', 'f3.in')
+SideEffect('log.txt', ['h1.out', 'g2.out', 'f3.out'])
+env.Build('log.out', 'log.txt')
+""" % locals())
+
+test.write('h1.in', 'h1.in\n')
+test.write('g2.in', 'g2.in\n')
+test.write('f3.in', 'f3.in\n')
+test.write('baz.in', 'baz.in\n')
+
+
+test.run(arguments = "-j 4 .")
+
+stdout = test.stdout()
+
+
+build_lines = [
+ 'build.py h1.in h1.out',
+ 'build.py g2.in g2.out',
+ 'build.py f3.in f3.out',
+]
+
+missing = []
+for line in build_lines:
+ if string.find(stdout, line) == -1:
+ missing.append(line)
+
+if missing:
+ print "===== standard output is missing the following lines:"
+ print string.join(missing, '\n')
+ print "===== STDOUT ========================================"
+ print stdout
+ test.fail_test()
+
+
+log = test.read('log.txt')
+
+log_lines = [
+ 'f3.in -> f3.out',
+ 'h1.in -> h1.out',
+ 'g2.in -> g2.out',
+]
+
+missing = []
+for line in log_lines:
+ if string.find(log, line) == -1:
+ missing.append(line)
+
+if missing:
+ print "===== log file 'log.txt' is missing the following lines:"
+ print string.join(missing, '\n')
+ print "===== STDOUT ==========================================="
+ print log
+ test.fail_test()
+
+
+test.pass_test()
diff --git a/test/Subst/AllowSubstExceptions.py b/test/Subst/AllowSubstExceptions.py
new file mode 100644
index 0000000..5709428
--- /dev/null
+++ b/test/Subst/AllowSubstExceptions.py
@@ -0,0 +1,93 @@
+#!/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__"
+
+"""
+XXX Put a description of the test here.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import SCons.Errors
+
+env = Environment(INDEX = [0, 1])
+
+assert env.subst('$NAME') == ''
+assert env.subst('${NAME}') == ''
+assert env.subst('${INDEX[999]}') == ''
+
+assert env.subst_list('$NAME') == [[]]
+assert env.subst_list('${NAME}') == [[]]
+assert env.subst_list('${INDEX[999]}') == [[]]
+
+AllowSubstExceptions()
+
+try: env.subst('$NAME')
+except SCons.Errors.UserError, e: print e
+else: raise Exception, "did not catch expected SCons.Errors.UserError"
+
+try: env.subst('${NAME}')
+except SCons.Errors.UserError, e: print e
+else: raise Exception, "did not catch expected SCons.Errors.UserError"
+
+try: env.subst('${INDEX[999]}')
+except SCons.Errors.UserError, e: print e
+else: raise Exception, "did not catch expected SCons.Errors.UserError"
+
+try: env.subst_list('$NAME')
+except SCons.Errors.UserError, e: print e
+else: raise Exception, "did not catch expected SCons.Errors.UserError"
+
+try: env.subst_list('${NAME}')
+except SCons.Errors.UserError, e: print e
+else: raise Exception, "did not catch expected SCons.Errors.UserError"
+
+try: env.subst_list('${INDEX[999]}')
+except SCons.Errors.UserError, e: print e
+else: raise Exception, "did not catch expected SCons.Errors.UserError"
+
+
+
+try: env.subst('${1/0}')
+except SCons.Errors.UserError, e: print e
+else: raise Exception, "did not catch expected SCons.Errors.UserError"
+
+try: env.subst_list('${1/0}')
+except SCons.Errors.UserError, e: print e
+else: raise Exception, "did not catch expected SCons.Errors.UserError"
+
+AllowSubstExceptions(ZeroDivisionError)
+
+assert env.subst('${1/0}') == ''
+assert env.subst_list('${1/0}') == [[]]
+""")
+
+test.run()
+#print test.stdout()
+
+test.pass_test()
diff --git a/test/Subst/SyntaxError.py b/test/Subst/SyntaxError.py
new file mode 100644
index 0000000..b37cdf4
--- /dev/null
+++ b/test/Subst/SyntaxError.py
@@ -0,0 +1,74 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if variable expansion
+throws a SyntaxError.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+
+expect_build = r"""scons: \*\*\*%s SyntaxError `invalid syntax( \((<string>, )?line 1\))?' trying to evaluate `%s'
+"""
+
+expect_read = "\n" + expect_build + TestSCons.file_expr
+
+
+# Syntax errors at SConscript read time:
+test.write('SConstruct', """\
+env = Environment()
+env.subst('$foo.bar.3.0')
+""")
+
+test.run(status=2, stderr=expect_read % ('', r'\$foo\.bar\.3\.0'))
+
+
+
+test.write('SConstruct', """\
+env = Environment()
+env.subst('${x ! y}')
+""")
+
+test.run(status=2, stderr=expect_read % ('', r'\$\{x \! y\}'))
+
+
+
+# Syntax errors at build time:
+test.write('SConstruct', """\
+env = Environment()
+env.Command('foo.bar', [], '$foo.bar.3.0')
+""")
+
+expect = expect_build % (r' \[foo\.bar\]', r'\$foo\.bar\.3\.0')
+
+test.run(status=2, stderr=expect)
+
+
+
+test.pass_test()
diff --git a/test/Subst/TypeError.py b/test/Subst/TypeError.py
new file mode 100644
index 0000000..d042b6d
--- /dev/null
+++ b/test/Subst/TypeError.py
@@ -0,0 +1,92 @@
+#!/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__"
+
+"""
+Verify the exit status and error output if variable expansion
+throws a TypeError.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+
+
+expect_build = r"""scons: \*\*\*%s TypeError `(unsubscriptable object|'NoneType' object is unsubscriptable)' trying to evaluate `%s'
+"""
+
+expect_read = "\n" + expect_build + TestSCons.file_expr
+
+# Type errors at SConscript read time:
+test.write('SConstruct', """\
+env = Environment(NONE = None)
+env.subst('${NONE[0]}')
+""")
+
+test.run(status=2, stderr=expect_read % ('', r'\$\{NONE\[0\]\}'))
+
+# Type errors at build time:
+test.write('SConstruct', """\
+env = Environment(NONE = None)
+env.Command('foo.bar', [], '${NONE[0]}')
+""")
+
+expect = expect_build % (r' \[foo\.bar\]', r'\$\{NONE\[0\]\}')
+
+test.run(status=2, stderr=expect)
+
+
+
+expect_build = r"""scons: \*\*\*%s TypeError `(not enough arguments; expected 3, got 1|func\(\) takes exactly 3 arguments \(1 given\))' trying to evaluate `%s'
+"""
+
+expect_read = "\n" + expect_build + TestSCons.file_expr
+
+# Type errors at SConscript read time:
+test.write('SConstruct', """\
+def func(a, b, c):
+ pass
+env = Environment(func = func)
+env.subst('${func(1)}')
+""")
+
+test.run(status=2, stderr=expect_read % ('', r'\$\{func\(1\)\}'))
+
+# Type errors at build time:
+test.write('SConstruct', """\
+def func(a, b, c):
+ pass
+env = Environment(func = func)
+env.Command('foo.bar', [], '${func(1)}')
+""")
+
+expect = expect_build % (r' \[foo\.bar\]', r'\$\{func\(1\)\}')
+
+test.run(status=2, stderr=expect)
+
+
+
+test.pass_test()
diff --git a/test/TEX/TEX.py b/test/TEX/TEX.py
index 7ea359b..eaea49a 100644
--- a/test/TEX/TEX.py
+++ b/test/TEX/TEX.py
@@ -174,9 +174,17 @@ Run \texttt{latex}, then \texttt{bibtex}, then \texttt{latex} twice again \cite{
test.run(stderr = None)
output_lines = string.split(test.stdout(), '\n')
- reruns = filter(lambda x: x == 'latex rerun.tex', output_lines)
- test.fail_test(len(reruns) != 2)
- bibtex = filter(lambda x: x == 'bibtex bibtex-test', output_lines)
- test.fail_test(len(bibtex) != 1)
+
+ reruns = filter(lambda x: string.find(x, 'latex rerun.tex') != -1, output_lines)
+ if len(reruns) != 2:
+ print "Expected 2 latex calls, got %s:" % len(reruns)
+ print string.join(reruns, '\n')
+ test.fail_test()
+
+ bibtex = filter(lambda x: string.find(x, 'bibtex bibtex-test') != -1, output_lines)
+ if len(bibtex) != 1:
+ print "Expected 1 bibtex call, got %s:" % len(bibtex)
+ print string.join(bibtex, '\n')
+ test.fail_test()
test.pass_test()
diff --git a/test/TEX/build_dir.py b/test/TEX/build_dir.py
new file mode 100644
index 0000000..146f6e1
--- /dev/null
+++ b/test/TEX/build_dir.py
@@ -0,0 +1,256 @@
+#!/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 creation of a fully-featured TeX document (with bibliography
+and index) in a build_dir.
+
+Test courtesy Rob Managan.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir(['docs'])
+
+
+test.write(['SConstruct'], """\
+import os
+
+env = Environment(ENV = { 'PATH' : os.environ['PATH'] })
+Export(['env'])
+
+SConscript(os.path.join('docs', 'SConscript'),
+ build_dir=os.path.join('mybuild','docs'),
+ duplicate=1)
+""")
+
+
+test.write(['docs', 'SConscript'], """\
+Import('env')
+
+test_dvi = env.DVI(source='test.tex')
+testpdf = env.PDF(source=test_dvi)
+""")
+
+
+test.write(['docs', 'Fig1.ps'], """\
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: Fig1.fig
+%%Creator: fig2dev Version 3.2 Patchlevel 4
+%%CreationDate: Tue Apr 25 09:56:11 2006
+%%For: managan@mangrove.llnl.gov (Rob Managan)
+%%BoundingBox: 0 0 98 98
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+
+end
+save
+newpath 0 98 moveto 0 0 lineto 98 0 lineto 98 98 lineto closepath clip newpath
+-24.9 108.2 translate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/sc {scale} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/tr {translate} bind def
+ /DrawEllipse {
+ /endangle exch def
+ /startangle exch def
+ /yrad exch def
+ /xrad exch def
+ /y exch def
+ /x exch def
+ /savematrix mtrx currentmatrix def
+ x y tr xrad yrad sc 0 0 1 startangle endangle arc
+ closepath
+ savematrix setmatrix
+ } def
+
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+10 setmiterlimit
+ 0.06299 0.06299 sc
+%
+% Fig objects follow
+%
+7.500 slw
+% Ellipse
+n 1170 945 766 766 0 360 DrawEllipse gs col0 s gr
+
+$F2psEnd
+rs
+""")
+
+
+test.write(['docs', 'Fig1.tex'],
+r"""\begin{picture}(0,0)%
+\includegraphics{Fig1.ps}%
+\end{picture}%
+\setlength{\unitlength}{4144sp}%
+%
+\begingroup\makeatletter\ifx\SetFigFont\undefined%
+\gdef\SetFigFont#1#2#3#4#5{%
+ \reset@font\fontsize{#1}{#2pt}%
+ \fontfamily{#3}\fontseries{#4}\fontshape{#5}%
+ \selectfont}%
+\fi\endgroup%
+\begin{picture}(1548,1546)(397,-879)
+\put(856,-196){\makebox(0,0)[lb]{\smash{\SetFigFont{12}{14.4}{\rmdefault}{\mddefault}{\updefault}{\color[rgb]{0,0,0}center $r_0$}%
+}}}
+\end{picture}
+""")
+
+
+test.write(['docs', 'test.bib'], """\
+%% This BibTeX bibliography file was created using BibDesk.
+%% http://bibdesk.sourceforge.net/
+
+
+%% Created for Rob Managan at 2006-11-15 12:53:16 -0800
+
+
+%% Saved with string encoding Western (ASCII)
+
+
+
+@techreport{Managan:2006fk,
+ Author = {Robert Managan},
+ Date-Added = {2006-11-15 12:51:30 -0800},
+ Date-Modified = {2006-11-15 12:52:35 -0800},
+ Institution = {none},
+ Month = {November},
+ Title = {A Test Paper},
+ Year = {2006}}
+""")
+
+
+test.write(['docs', 'test.tex'],
+r"""\documentclass{report}
+
+\usepackage{graphicx}
+\usepackage{epsfig,color} % for .tex version of figures if we go that way
+
+\usepackage{makeidx}
+\makeindex
+
+\begin{document}
+
+\title{Report Title}
+
+\author{A. N. Author}
+
+\maketitle
+
+\begin{abstract}
+there is no abstract
+\end{abstract}
+
+\tableofcontents
+\listoffigures
+
+\chapter{Introduction}
+
+The introduction is short.
+
+\index{Acknowledgements}
+
+\section{Acknowledgements}
+
+The Acknowledgements are show as well \cite{Managan:2006fk}.
+
+\index{Getting the Report}
+
+To get a hard copy of this report call me.
+
+\begin{figure}[htbp]
+\begin{center}
+\input{Fig1.tex} % testing figure variant that uses TeX labeling
+\caption{Zone and Node indexing}
+\label{fig1}
+\end{center}
+\end{figure}
+
+All done now.
+
+\bibliographystyle{unsrt}
+\bibliography{test}
+\newpage
+
+\printindex
+
+\end{document}
+""")
+
+
+# makeindex will write status messages to stderr (grrr...), so ignore it.
+test.run(arguments = '.', stderr=None)
+
+
+# All (?) the files we expect will get created in the build_dir
+# (mybuild/docs) and not in the srcdir (docs).
+files = [
+ 'test.aux',
+ 'test.bbl',
+ 'test.blg',
+ 'test.dvi',
+ 'test.idx',
+ 'test.ilg',
+ 'test.ind',
+ 'test.lof',
+ 'test.log',
+ 'test.pdf',
+ 'test.toc',
+]
+
+for f in files:
+ test.must_exist(['mybuild', 'docs', f])
+ test.must_not_exist(['docs', f])
+
+
+test.pass_test()
diff --git a/test/TEX/subdir-input.py b/test/TEX/subdir-input.py
new file mode 100644
index 0000000..b92ab73
--- /dev/null
+++ b/test/TEX/subdir-input.py
@@ -0,0 +1,80 @@
+#!/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__"
+
+"""
+Verify that we execute TeX in a subdirectory (if that's where the document
+resides) by checking that all the auxiliary files get created there and
+not in the top-level directory.
+
+Also check that we find files
+
+Test case courtesy Joel B. Mohler.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('sub')
+
+test.write('SConstruct', """\
+PDF( 'sub/x.tex' )
+DVI( 'sub/x.tex' )
+""")
+
+test.write(['sub', 'x.tex'],
+r"""\documentclass{article}
+\begin{document}
+Hi there.
+\input{y}
+\end{document}
+""")
+
+test.write(['sub', 'y.tex'], """\
+Sub-document 1
+""")
+
+test.run(arguments = '.')
+
+test.must_exist(['sub', 'x.aux'])
+test.must_exist(['sub', 'x.dvi'])
+test.must_exist(['sub', 'x.log'])
+test.must_exist(['sub', 'x.pdf'])
+
+test.must_not_exist('x.aux')
+test.must_not_exist('x.dvi')
+test.must_not_exist('x.log')
+test.must_not_exist('x.pdf')
+
+test.up_to_date(arguments = '.')
+
+test.write(['sub', 'y.tex'], """\
+Sub-document 2
+""")
+
+test.not_up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/errors.py b/test/errors.py
deleted file mode 100644
index 6e0a05f..0000000
--- a/test/errors.py
+++ /dev/null
@@ -1,224 +0,0 @@
-#!/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__"
-
-import TestCmd
-import TestSCons
-import string
-import sys
-
-_python_ = TestSCons._python_
-
-test = TestSCons.TestSCons(match = TestCmd.match_re_dotall)
-
-
-
-test.write('foo.in', 'foo\n')
-
-test.write('exit.in', 'exit\n')
-
-test.write('SConstruct', """\
-import sys
-
-def foo(env, target, source):
- print str(target[0])
- open(str(target[0]), 'wt').write('foo')
-
-def exit(env, target, source):
- raise 'exit'
-
-env = Environment(BUILDERS = { 'foo' : Builder(action=foo),
- 'exit' : Builder(action=exit) })
-
-env.foo('foo.out', 'foo.in')
-env.exit('exit.out', 'exit.in')
-""")
-
-# print_exception doesn't always show a source line if the source file
-# no longer exists or that line in the source file no longer exists,
-# so make sure the proper variations are supported in the following
-# regexp.
-stderr = """scons: \*\*\* \[exit.out\] Exception
-Traceback \((most recent call|innermost) last\):
-( File ".+", line \d+, in \S+
- [^\n]+
-)*( File ".+", line \d+, in \S+
-)*( File ".+", line \d+, in \S+
- [^\n]+
-)*\S.+
-"""
-
-test.run(arguments='foo.out exit.out', stderr=stderr, status=2)
-
-test.run(arguments='foo.out exit.out', stderr=stderr, status=2)
-assert string.find(test.stdout(), "scons: `foo.out' is up to date.") != -1, test.stdout()
-
-
-
-# Test AttributeError.
-test.write('SConstruct', """\
-a = 1
-a.append(2)
-""")
-
-test.run(status = 2, stderr = """\
-AttributeError: 'int' object has no attribute 'append':
- File ".+SConstruct", line 2:
- a.append\(2\)
-""")
-
-
-
-# Test NameError.
-test.write('SConstruct', """\
-a == 1
-""")
-
-test.run(status = 2, stderr = """\
-NameError: [^\n]*
- File ".+SConstruct", line 1:
- a == 1
-""")
-
-
-
-# Test SyntaxError.
-test.write('SConstruct', """
-a ! x
-""")
-
-test.run(stdout = "scons: Reading SConscript files ...\n",
- stderr = """ File ".+SConstruct", line 2
-
- a ! x
-
- \^
-
-SyntaxError: invalid syntax
-
-""", status=2)
-
-
-
-# Test TypeError.
-test.write('SConstruct', """\
-a = 1
-a[2] = 3
-""")
-
-test.run(status = 2, stderr = """\
-TypeError: object does not support item assignment:
- File ".+SConstruct", line 2:
- a\[2\] = 3
-""")
-
-
-
-# Test UserError.
-test.write('SConstruct', """
-assert not globals().has_key("UserError")
-import SCons.Errors
-raise SCons.Errors.UserError, 'Depends() require both sources and targets.'
-""")
-
-test.run(stdout = "scons: Reading SConscript files ...\n",
- stderr = """
-scons: \*\*\* Depends\(\) require both sources and targets.
-File ".+SConstruct", line 4, in \?
-""", status=2)
-
-
-
-# Test InternalError.
-test.write('SConstruct', """
-assert not globals().has_key("InternalError")
-from SCons.Errors import InternalError
-raise InternalError, 'error inside'
-""")
-
-test.run(stdout = "scons: Reading SConscript files ...\ninternal error\n",
- stderr = r"""Traceback \((most recent call|innermost) last\):
- File ".+", line \d+, in .+
- File ".+", line \d+, in .+
- File ".+", line \d+, in .+
- File ".+SConstruct", line \d+, in \?
- raise InternalError, 'error inside'
-InternalError: error inside
-""", status=2)
-
-test.write('build.py', '''
-import sys
-sys.exit(2)
-''')
-
-
-
-# Test ...
-test.write('SConstruct', """
-env=Environment()
-Default(env.Command(['one.out', 'two.out'],
- ['foo.in'],
- action=r'%(_python_)s build.py'))
-""" % locals())
-
-test.run(status=2, stderr="scons: \\*\\*\\* \\[one.out\\] Error 2\n")
-
-
-
-# Test syntax errors when trying to expand construction variables.
-test.write('SConstruct', """\
-env = Environment()
-env.subst('$foo.bar.3.0')
-""")
-
-test.run(status=2, stderr="""
-scons: \*\*\* Syntax error `invalid syntax( \(line 1\))?' trying to evaluate `\$foo\.bar\.3\.0'
-File "[^"]+", line \d+, in \S+
-""")
-
-test.write('SConstruct', """\
-env = Environment()
-env.subst_list('$foo.3.0.x')
-""")
-
-test.run(status=2, stderr="""
-scons: \*\*\* Syntax error `invalid syntax( \(line 1\))?' trying to evaluate `\$foo\.3\.0\.x'
-File "[^"]+", line \d+, in \S+
-""")
-
-#Test syntax errors when trying to expand construction variables at build time:
-test.write('SConstruct', """\
-env = Environment()
-env.Command('foo.bar', [], '$foo.bar.3.0')
-""")
-
-test.run(status=2, stderr=r"""scons: \*\*\* \[foo\.bar\] Syntax error `invalid syntax( \(line 1\))?' trying to evaluate `\$foo\.bar\.3\.0'
-""")
-
-
-
-
-
-test.pass_test()
diff --git a/test/import.py b/test/import.py
index bb070ab..92797df 100644
--- a/test/import.py
+++ b/test/import.py
@@ -29,6 +29,9 @@ Verify that we can import and use the contents of Platform and Tool
modules directly.
"""
+import re
+import sys
+
import TestSCons
test = TestSCons.TestSCons()
@@ -49,10 +52,10 @@ platforms = [
for platform in platforms:
test.write('SConstruct', """
-env = Environment(platform = '%s')
-import SCons.Platform.%s
-x = SCons.Platform.%s.generate
-""" % (platform, platform, platform))
+env = Environment(platform = '%(platform)s')
+import SCons.Platform.%(platform)s
+x = SCons.Platform.%(platform)s.generate
+""" % locals())
test.run()
tools = [
@@ -139,46 +142,33 @@ tools = [
'zip',
]
-# Intel no compiler warning..
-intel_no_compiler_fmt = """
-scons: warning: Failed to find Intel compiler for version='None', abi='%(abi)s'
-File "%(SConstruct_path)s", line 1, in ?
-"""
-
-abi = 'ia32'
-intel_no_compiler_32_warning = intel_no_compiler_fmt % locals()
+if sys.platform == 'win32':
+ tools.extend([
+ '386asm',
+ 'linkloc',
+ ])
-abi = 'x86_64'
-intel_no_compiler_64_warning = intel_no_compiler_fmt % locals()
+# Intel no compiler warning..
+intel_no_compiler_warning = """
+scons: warning: Failed to find Intel compiler for version='None', abi='[^']*'
+""" + TestSCons.file_expr
# Intel no top dir warning.
-intel_no_top_dir_fmt = """
-scons: warning: Can't find Intel compiler top dir for version='None', abi='%(abi)s'
-File "%(SConstruct_path)s", line 1, in ?
-""" % locals()
-
-abi = 'ia32'
-intel_no_top_dir_32_warning = intel_no_top_dir_fmt % locals()
-
-abi = 'x86_64'
-intel_no_top_dir_64_warning = intel_no_top_dir_fmt % locals()
+intel_no_top_dir_warning = """
+scons: warning: Can't find Intel compiler top dir for version='None', abi='[^']*'
+""" + TestSCons.file_expr
# Intel no license directory warning
-intel_license_warning = """
+intel_license_warning = re.escape("""
scons: warning: Intel license dir was not found. Tried using the INTEL_LICENSE_FILE environment variable (), the registry () and the default path (C:\Program Files\Common Files\Intel\Licenses). Using the default path as a last resort.
-File "%(SConstruct_path)s", line 1, in ?
-""" % locals()
+""") + TestSCons.file_expr
intel_warnings = [
- intel_license_warning,
- intel_no_compiler_32_warning,
- intel_no_compiler_32_warning + intel_license_warning,
- intel_no_compiler_64_warning,
- intel_no_compiler_64_warning + intel_license_warning,
- intel_no_top_dir_32_warning,
- intel_no_top_dir_32_warning + intel_license_warning,
- intel_no_top_dir_64_warning,
- intel_no_top_dir_64_warning + intel_license_warning,
+ re.compile(intel_license_warning),
+ re.compile(intel_no_compiler_warning),
+ re.compile(intel_no_compiler_warning + intel_license_warning),
+ re.compile(intel_no_top_dir_warning),
+ re.compile(intel_no_top_dir_warning + intel_license_warning),
]
moc = test.where_is('moc')
@@ -189,50 +179,60 @@ if moc:
qt_err = """
scons: warning: Could not detect qt, using moc executable as a hint (QTDIR=%(qtdir)s)
-File "%(SConstruct_path)s", line 1, in ?
""" % locals()
else:
qt_err = """
scons: warning: Could not detect qt, using empty QTDIR
-File "%(SConstruct_path)s", line 1, in ?
-""" % locals()
+"""
+
+qt_warnings = [ re.compile(qt_err + TestSCons.file_expr) ]
error_output = {
'icl' : intel_warnings,
'intelc' : intel_warnings,
- 'qt' : [qt_err],
+ 'qt' : qt_warnings,
}
# An SConstruct for importing Tool names that have illegal characters
# for Python variable names.
indirect_import = """\
-env = Environment(tools = ['%s'])
-SCons = __import__('SCons.Tool.%s', globals(), locals(), [])
-m = getattr(SCons.Tool, '%s')
-x = m.generate
+env = Environment(tools = ['%(tool)s'])
+
+SCons = __import__('SCons.Tool.%(tool)s', globals(), locals(), [])
+m = getattr(SCons.Tool, '%(tool)s')
+env = Environment()
+m.generate(env)
"""
# An SConstruct for importing Tool names "normally."
direct_import = """\
-env = Environment(tools = ['%s'])
-import SCons.Tool.%s
-x = SCons.Tool.%s.generate
+env = Environment(tools = ['%(tool)s'])
+
+import SCons.Tool.%(tool)s
+env = Environment()
+SCons.Tool.%(tool)s.generate(env)
"""
failures = []
for tool in tools:
if tool[0] in '0123456789' or '+' in tool:
- test.write('SConstruct', indirect_import % (tool, tool, tool))
+ test.write('SConstruct', indirect_import % locals())
else:
- test.write('SConstruct', direct_import % (tool, tool, tool))
+ test.write('SConstruct', direct_import % locals())
test.run(stderr=None)
stderr = test.stderr()
- if not stderr in [''] + error_output.get(tool, []):
- print "Failed importing '%s', stderr:" % tool
- print stderr
- failures.append(tool)
+ if stderr:
+ matched = None
+ for expression in error_output.get(tool, []):
+ if expression.match(stderr):
+ matched = 1
+ break
+ if not matched:
+ print "Failed importing '%s', stderr:" % tool
+ print stderr
+ failures.append(tool)
test.fail_test(len(failures))
diff --git a/test/option-c.py b/test/option-c.py
index 7ab4129..e709709 100644
--- a/test/option-c.py
+++ b/test/option-c.py
@@ -177,10 +177,27 @@ test.must_match(test.workpath('foo4.out'), "foo4.in\n")
test.must_exist(test.workpath('touch1.out'))
test.must_exist(test.workpath('touch2.out'))
+
+expect1 = "scons: Could not remove 'foo1.out': Permission denied\n"
+expect2 = "scons: Could not remove 'foo1.out': The process cannot access the file because it is being used by another process\n"
+
+expect = [
+ test.wrap_stdout(expect1, cleaning=1),
+ test.wrap_stdout(expect2, cleaning=1),
+]
+
test.writable('.', 0)
f = open(test.workpath('foo1.out'))
-test.run(arguments = '-c foo1.out',
- stdout = test.wrap_stdout("scons: Could not remove 'foo1.out': Permission denied\n", cleaning=1))
+test.run(arguments = '-c foo1.out')
+stdout = test.stdout()
+matched = None
+for e in expect:
+ if stdout == e:
+ matched = 1
+ break
+if not matched:
+ print stdout
+ test.fail_test()
test.must_exist(test.workpath('foo1.out'))
f.close()
test.writable('.', 1)
diff --git a/test/option-v.py b/test/option-v.py
index 28fe8ca..0626106 100644
--- a/test/option-v.py
+++ b/test/option-v.py
@@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestCmd
import TestSCons
+import re
import string
import sys
@@ -33,26 +34,38 @@ test = TestSCons.TestSCons(match = TestCmd.match_re)
test.write('SConstruct', "")
+# Construct the standard copyright marker so it doesn't get replaced
+# by the packaging build.
+copyright_marker = '__' + 'COPYRIGHT' + '__'
+
+copyright_years = '2001, 2002, 2003, 2004, 2005, 2006'
+
+fmt = '(%s|Copyright \\(c\\) %s The SCons Foundation)\n'
+
+copyright_line = fmt % (copyright_marker, copyright_years)
+
# Windows may or may not print a line for the script version
# depending on whether it's invoked through scons.py or scons.bat.
expect1 = r"""SCons by Steven Knight et al.:
\tengine: v\S+, [^,]*, by \S+ on \S+
-(__COPYRIGHT__|Copyright \(c\) 2001, 2002, 2003, 2004 The SCons Foundation)
-"""
+""" + copyright_line
expect2 = r"""SCons by Steven Knight et al.:
\tscript: v\S+, [^,]*, by \S+ on \S+
\tengine: v\S+, [^,]*, by \S+ on \S+
-(__COPYRIGHT__|Copyright \(c\) 2001, 2002, 2003, 2004 The SCons Foundation)
-"""
+""" + copyright_line
test.run(arguments = '-v')
-test.fail_test(not test.match_re(test.stdout(), expect1) and
- not test.match_re(test.stdout(), expect2))
+stdout = test.stdout()
+if not test.match_re(stdout, expect1) and not test.match_re(stdout, expect2):
+ print stdout
+ test.fail_test()
test.run(arguments = '--version')
-test.fail_test(not test.match_re(test.stdout(), expect1) and
- not test.match_re(test.stdout(), expect2))
+stdout = test.stdout()
+if not test.match_re(stdout, expect1) and not test.match_re(stdout, expect2):
+ print stdout
+ test.fail_test()
test.pass_test()
diff --git a/test/option/debug-memoizer.py b/test/option/debug-memoizer.py
index c9f001c..33f0f4d 100644
--- a/test/option/debug-memoizer.py
+++ b/test/option/debug-memoizer.py
@@ -33,7 +33,23 @@ import string
import TestSCons
-test = TestSCons.TestSCons()
+test = TestSCons.TestSCons(match = TestSCons.match_re)
+
+# Find out if we support metaclasses (Python 2.2 and later).
+
+class M:
+ def __init__(cls, name, bases, cls_dict):
+ cls.has_metaclass = 1
+
+class A:
+ __metaclass__ = M
+
+try:
+ has_metaclass = A.has_metaclass
+except AttributeError:
+ has_metaclass = None
+
+
test.write('SConstruct', """
def cat(target, source, env):
@@ -50,21 +66,47 @@ test.write('file.in', "file.in\n")
# change this test...
expect = [
"Memoizer (memory cache) hits and misses",
- "Dir.exists()",
+ "Base.stat()",
+ "Dir.srcdir_list()",
"File.exists()",
- "SConsEnvironment.Detect()",
+ "FS._doLookup()",
+ "Node._children_get()",
]
+expect_no_metaclasses = """
+scons: warning: memoization is not supported in this version of Python \\(no metaclasses\\)
+""" + TestSCons.file_expr
+
+
+if has_metaclass:
+
+ def run_and_check(test, args, desc):
+ test.run(arguments = args)
+ stdout = test.stdout()
+ missing = filter(lambda e, s=stdout: string.find(s, e) == -1, expect)
+ if missing:
+ print "Missing the following strings in the %s output:" % desc
+ print " " + string.join(missing, "\n ")
+ print "STDOUT ============"
+ print stdout
+ test.fail_test()
+
+else:
+
+ def run_and_check(test, args, desc):
+ test.run(arguments = args, stderr = expect_no_metaclasses)
+ stdout = test.stdout()
+ present = filter(lambda e, s=stdout: string.find(s, e) != -1, expect)
+ if present:
+ print "The following unexpected strings are present in the %s output:" % desc
+ print " " + string.join(present, "\n ")
+ print "STDOUT ============"
+ print stdout
+ test.fail_test()
+
+
for args in ['-h --debug=memoizer', '--debug=memoizer']:
- test.run(arguments = args)
- stdout = test.stdout()
- missing = filter(lambda e, s=stdout: string.find(s, e) == -1, expect)
- if missing:
- print "Missing the following strings in the command line '%s' output:" % args
- print " " + string.join(missing, "\n ")
- print "STDOUT ============"
- print stdout
- test.fail_test(1)
+ run_and_check(test, args, "command line '%s'" % args)
test.must_match('file.out', "file.in\n")
@@ -72,17 +114,13 @@ test.must_match('file.out', "file.in\n")
test.unlink("file.out")
+
+
os.environ['SCONSFLAGS'] = '--debug=memoizer'
-test.run()
-stdout = test.stdout()
-missing = filter(lambda e, s=stdout: string.find(s, e) == -1, expect)
-if missing:
- print "Missing the following strings in the SCONSFLAGS=--debug=memoizer output:"
- print " " + string.join(missing, "\n ")
- print "STDOUT ============"
- print stdout
- test.fail_test(1)
+run_and_check(test, '', 'SCONSFLAGS=--debug=memoizer')
+
+test.must_match('file.out', "file.in\n")
diff --git a/test/option/debug-nomemoizer.py b/test/option/debug-nomemoizer.py
index 633a46d..3a927e5 100644
--- a/test/option/debug-nomemoizer.py
+++ b/test/option/debug-nomemoizer.py
@@ -25,19 +25,12 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-Test calling the --debug=nomemoizer option.
+Test calling the (deprecated) --debug=nomemoizer option.
"""
-import pstats
-import string
-import StringIO
-import sys
-
import TestSCons
-test = TestSCons.TestSCons()
-
-scons_prof = test.workpath('scons.prof')
+test = TestSCons.TestSCons(match = TestSCons.match_re)
test.write('SConstruct', """
def cat(target, source, env):
@@ -48,25 +41,12 @@ env.Cat('file.out', 'file.in')
test.write('file.in', "file.in\n")
-test.run(arguments = "--profile=%s --debug=nomemoizer " % scons_prof)
-
-stats = pstats.Stats(scons_prof)
-stats.sort_stats('time')
-
-try:
- save_stdout = sys.stdout
- sys.stdout = StringIO.StringIO()
-
- stats.strip_dirs().print_stats()
+expect = """
+scons: warning: The --debug=nomemoizer option is deprecated and has no effect.
+""" + TestSCons.file_expr
- s = sys.stdout.getvalue()
-finally:
- sys.stdout = save_stdout
+test.run(arguments = "--debug=nomemoizer", stderr = expect)
-test.fail_test(string.find(s, '_MeMoIZeR_init') != -1)
-test.fail_test(string.find(s, '_MeMoIZeR_reset') != -1)
-test.fail_test(string.find(s, 'Count_cache_get') != -1)
-test.fail_test(string.find(s, 'Count_cache_get_self') != -1)
-test.fail_test(string.find(s, 'Count_cache_get_one') != -1)
+test.must_match('file.out', "file.in\n")
test.pass_test()
diff --git a/test/option/profile.py b/test/option/profile.py
index 9207066..eb6b394 100644
--- a/test/option/profile.py
+++ b/test/option/profile.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import pstats
import string
import StringIO
import sys
@@ -33,6 +32,11 @@ import TestSCons
test = TestSCons.TestSCons()
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
test.write('SConstruct', """\
Command('file.out', 'file.in', Copy("$TARGET", "$SOURCE"))
""")
diff --git a/test/scons-time/func/basic.py b/test/scons-time/func/basic.py
new file mode 100644
index 0000000..66c5853
--- /dev/null
+++ b/test/scons-time/func/basic.py
@@ -0,0 +1,49 @@
+#!/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__"
+
+"""
+Verify basic operation of the "func" subcommand.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
+test.profile_data('foo.prof', 'prof.py', '_main', """\
+def _main():
+ pass
+""")
+
+expect = r'\d.\d\d\d prof\.py:1\(_main\)' + '\n'
+
+test.run(arguments = 'func foo.prof', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/func/chdir.py b/test/scons-time/func/chdir.py
new file mode 100644
index 0000000..80ec93e
--- /dev/null
+++ b/test/scons-time/func/chdir.py
@@ -0,0 +1,64 @@
+#!/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__"
+
+"""
+Verify that the func -C and --chdir options change directory before
+globbing for files.
+"""
+
+import re
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
+test.subdir('profs')
+
+input = """\
+def _main():
+ pass
+"""
+
+expect = []
+for i in xrange(9):
+ i = str(i)
+ test.subdir(i)
+ test.profile_data('profs/foo-%s.prof' % i, '%s/prof.py' % i, '_main', input)
+ s = r'\d.\d\d\d %s/prof\.py:1\(_main\)' % re.escape(test.workpath(i))
+ expect.append(s + '\n')
+
+expect = ''.join(expect)
+
+test.run(arguments = 'func -C profs foo-*.prof', stdout = expect)
+
+test.run(arguments = 'func --chdir profs foo-?.prof', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/func/file.py b/test/scons-time/func/file.py
new file mode 100644
index 0000000..c9486c4
--- /dev/null
+++ b/test/scons-time/func/file.py
@@ -0,0 +1,80 @@
+#!/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__"
+
+"""
+Verify that config files specified with the -f and --file options
+affect how the func subcommand processes things.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
+test.profile_data('foo-001-0.prof', 'prof1.py', '_main', """\
+def _main():
+ pass
+""")
+
+test.profile_data('foo-002-0.prof', 'prof2.py', '_main', """\
+# line 1 (intentional comment to adjust starting line numbers)
+def _main():
+ pass
+""")
+
+
+test.write('st1.conf', """\
+prefix = 'foo-001'
+""")
+
+expect1 = r'\d.\d\d\d prof1\.py:1\(_main\)' + '\n'
+
+test.run(arguments = 'func -f st1.conf', stdout = expect1)
+
+
+test.write('st2.conf', """\
+prefix = 'foo'
+title = 'ST2.CONF TITLE'
+""")
+
+expect2 = \
+r"""set title "ST2.CONF TITLE"
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+1 0.000
+2 0.000
+e
+"""
+
+test.run(arguments = 'func --file st2.conf --fmt gnuplot', stdout = expect2)
+
+
+test.pass_test()
diff --git a/test/scons-time/func/format-gnuplot.py b/test/scons-time/func/format-gnuplot.py
new file mode 100644
index 0000000..92eb837
--- /dev/null
+++ b/test/scons-time/func/format-gnuplot.py
@@ -0,0 +1,82 @@
+#!/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__"
+
+"""
+Verify the func --format=gnuplot option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
+content = """\
+def _main():
+ pass
+"""
+
+test.profile_data('foo-000-0.prof', 'prof.py', '_main', content)
+test.profile_data('foo-000-1.prof', 'prof.py', '_main', content)
+test.profile_data('foo-000-2.prof', 'prof.py', '_main', content)
+
+test.profile_data('foo-001-0.prof', 'prof.py', '_main', content)
+test.profile_data('foo-001-1.prof', 'prof.py', '_main', content)
+test.profile_data('foo-001-2.prof', 'prof.py', '_main', content)
+
+expect_notitle = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1, \\
+ '-' title "Full build" with lines lt 2, \\
+ '-' title "Up-to-date build" with lines lt 3
+# Startup
+0 0.000
+1 0.000
+e
+# Full build
+0 0.000
+1 0.000
+e
+# Up-to-date build
+0 0.000
+1 0.000
+e
+"""
+
+expect_title = 'set title "TITLE"\n' + expect_notitle
+
+test.run(arguments = 'func --fmt gnuplot', stdout=expect_notitle)
+
+test.run(arguments = 'func --fmt=gnuplot --title TITLE', stdout=expect_title)
+
+test.run(arguments = 'func --format gnuplot --title TITLE', stdout=expect_title)
+
+test.run(arguments = 'func --format=gnuplot', stdout=expect_notitle)
+
+test.pass_test()
diff --git a/test/scons-time/func/function.py b/test/scons-time/func/function.py
new file mode 100644
index 0000000..27bb94d
--- /dev/null
+++ b/test/scons-time/func/function.py
@@ -0,0 +1,58 @@
+#!/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__"
+
+"""
+Verify use of the --func and --function options to select functions
+other than the default _main().
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
+test.profile_data('foo.prof', 'prof.py', '_main', """\
+def f1():
+ pass
+def f3():
+ pass
+def _main():
+ f1()
+ f3()
+""")
+
+expect1 = r'\d.\d\d\d prof\.py:1\(f1\)' + '\n'
+expect3 = r'\d.\d\d\d prof\.py:3\(f3\)' + '\n'
+
+test.run(arguments = 'func --func f1 foo.prof', stdout = expect1)
+
+test.run(arguments = 'func --function f3 foo.prof', stdout = expect3)
+
+test.pass_test()
diff --git a/test/scons-time/func/glob.py b/test/scons-time/func/glob.py
new file mode 100644
index 0000000..4a629ed
--- /dev/null
+++ b/test/scons-time/func/glob.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify that the func subcommands globs for files.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
+input = """\
+def _main():
+ pass
+"""
+
+expect = []
+for i in xrange(9):
+ test.subdir(str(i))
+ test.profile_data('foo-%s.prof' % i, '%s/prof.py' % i, '_main', input)
+ expect.append((r'\d.\d\d\d %s/prof\.py:1\(_main\)' + '\n') % i)
+
+expect = ''.join(expect)
+
+test.run(arguments = 'func foo-*.prof', stdout = expect)
+
+test.run(arguments = 'func foo-?.prof', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/func/help.py b/test/scons-time/func/help.py
new file mode 100644
index 0000000..7341ade
--- /dev/null
+++ b/test/scons-time/func/help.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify the func subcommand help.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = [
+ "Usage: scons-time func [OPTIONS] FILE [...]\n",
+ " -C DIR, --chdir=DIR Change to DIR before looking for files\n",
+ " -h, --help Print this help and exit\n",
+]
+
+test.run(arguments = 'func -h')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'func -?')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'func --help')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'help func')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.pass_test()
diff --git a/test/scons-time/func/no-args.py b/test/scons-time/func/no-args.py
new file mode 100644
index 0000000..0767ae6
--- /dev/null
+++ b/test/scons-time/func/no-args.py
@@ -0,0 +1,43 @@
+#!/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__"
+
+"""
+Verify the error from the func subcommand when no arguments are specified.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = """\
+scons-time: func: No arguments specified.
+ No *.prof files found in "%s".
+ Type "scons-time help func" for help.
+""" % test.workpath()
+
+test.run(arguments = 'func', status = 1, stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/func/prefix.py b/test/scons-time/func/prefix.py
new file mode 100644
index 0000000..53dfea6
--- /dev/null
+++ b/test/scons-time/func/prefix.py
@@ -0,0 +1,65 @@
+#!/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__"
+
+"""
+Verify that the func -p and --prefix options specify what log files to use.
+"""
+
+import os.path
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
+input = """\
+def _main():
+ pass
+"""
+
+foo_lines = []
+bar_lines = []
+
+for i in xrange(2):
+ test.profile_data('foo-%s.prof' % i, 'prof.py', '_main', input)
+ foo_lines.append(r'\d.\d\d\d prof\.py:1\(_main\)' + '\n')
+
+for i in xrange(4):
+ test.profile_data('bar-%s.prof' % i, 'prof.py', '_main', input)
+ bar_lines.append(r'\d.\d\d\d prof\.py:1\(_main\)' + '\n')
+
+foo_expect = ''.join(foo_lines)
+bar_expect = ''.join(bar_lines)
+
+test.run(arguments = 'func -p bar', stdout = bar_expect)
+
+test.run(arguments = 'func --prefix=foo', stdout = foo_expect)
+
+test.pass_test()
diff --git a/test/scons-time/func/tail.py b/test/scons-time/func/tail.py
new file mode 100644
index 0000000..816a7a1
--- /dev/null
+++ b/test/scons-time/func/tail.py
@@ -0,0 +1,56 @@
+#!/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__"
+
+"""
+Verify that the func subcommand only prints results for the last number
+of files specified with the -t and --tail options.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+
+try:
+ import pstats
+except ImportError:
+ test.skip_test('No pstats module, skipping test.\n')
+
+input = """\
+def _main():
+ pass
+"""
+
+expect = []
+for i in xrange(9):
+ test.subdir(str(i))
+ test.profile_data('foo-%s.prof' % i, '%s/prof.py' % i, '_main', input)
+ expect.append((r'\d.\d\d\d %s/prof\.py:1\(_main\)' + '\n') % i)
+
+test.run(arguments = 'func -t 3 foo-*.prof', stdout = ''.join(expect[-3:]))
+
+test.run(arguments = 'func --tail 5 foo-*.prof', stdout = ''.join(expect[-5:]))
+
+test.pass_test()
diff --git a/test/scons-time/help/all-subcommands.py b/test/scons-time/help/all-subcommands.py
new file mode 100644
index 0000000..6fa0fac
--- /dev/null
+++ b/test/scons-time/help/all-subcommands.py
@@ -0,0 +1,58 @@
+#!/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__"
+
+"""
+Verify that all subcommands show up in the global help.
+
+This makes sure that each do_*() function attached to the SConsTimer
+class has a line in the help string.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+# Compile the scons-time script as a module.
+c = compile(test.read(test.program, mode='r'), test.program, 'exec')
+
+# Evaluate the module in a global name space so we can get at SConsTimer.
+globals = {}
+try: eval(c, globals)
+except: pass
+
+# Extract all subcommands from the the do_*() functions.
+functions = globals['SConsTimer'].__dict__.keys()
+do_funcs = filter(lambda x: x[:3] == 'do_', functions)
+
+subcommands = map(lambda x: x[3:], do_funcs)
+
+expect = map(lambda x: ' %s ' % x, subcommands)
+
+test.run(arguments = 'help')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.pass_test()
diff --git a/test/scons-time/help/options.py b/test/scons-time/help/options.py
new file mode 100644
index 0000000..942dfa6
--- /dev/null
+++ b/test/scons-time/help/options.py
@@ -0,0 +1,59 @@
+#!/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__"
+
+"""
+Verify that the 'help' subcommand and -h, -? and --help options print
+the default help.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = [
+ 'Usage: scons-time SUBCOMMAND [ARGUMENTS]\n',
+ 'Type "scons-time help SUBCOMMAND" for help on a specific subcommand.\n',
+ 'Available subcommands:\n',
+ ' help Provides help\n',
+]
+
+test.run(arguments = 'help')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = '-h')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = '-?')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = '--help')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.pass_test()
diff --git a/test/scons-time/mem/chdir.py b/test/scons-time/mem/chdir.py
new file mode 100644
index 0000000..a97f756
--- /dev/null
+++ b/test/scons-time/mem/chdir.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify that the mem -C and --chdir options change directory before
+globbing for files.
+"""
+
+import os.path
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.subdir('logs')
+
+lines = [
+ ' pre-read post-read pre-build post-build\n'
+]
+
+line_fmt = ' 1000 2000 3000 4000 %s\n'
+
+for i in xrange(9):
+ logfile_name = os.path.join('logs', 'foo-%s.log' % i)
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % logfile_name)
+
+expect = ''.join(lines)
+
+test.run(arguments = 'mem -C logs foo-*.log', stdout = expect)
+
+test.run(arguments = 'mem --chdir logs foo-?.log', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/mem/file.py b/test/scons-time/mem/file.py
new file mode 100644
index 0000000..a236df7
--- /dev/null
+++ b/test/scons-time/mem/file.py
@@ -0,0 +1,71 @@
+#!/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__"
+
+"""
+Verify that config files specified with the -f and --file options
+affect how the mem subcommand processes things.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-001-0.log')
+
+test.fake_logfile('foo-002-0.log')
+
+
+test.write('st1.conf', """\
+prefix = 'foo-001'
+""")
+
+expect1 = """\
+ pre-read post-read pre-build post-build
+ 1000 2000 3000 4000 foo-001-0.log
+"""
+
+test.run(arguments = 'mem -f st1.conf', stdout = expect1)
+
+
+test.write('st2.conf', """\
+prefix = 'foo'
+title = 'ST2.CONF TITLE'
+""")
+
+expect2 = \
+r"""set title "ST2.CONF TITLE"
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+1 4000.000
+2 4000.000
+e
+"""
+
+test.run(arguments = 'mem --file st2.conf --fmt gnuplot', stdout = expect2)
+
+
+test.pass_test()
diff --git a/test/scons-time/mem/format-gnuplot.py b/test/scons-time/mem/format-gnuplot.py
new file mode 100644
index 0000000..a4e0f19
--- /dev/null
+++ b/test/scons-time/mem/format-gnuplot.py
@@ -0,0 +1,72 @@
+#!/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__"
+
+"""
+Verify the mem --format=gnuplot option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-000-0.log', 0)
+test.fake_logfile('foo-000-1.log', 0)
+test.fake_logfile('foo-000-2.log', 0)
+
+test.fake_logfile('foo-001-0.log', 1)
+test.fake_logfile('foo-001-1.log', 1)
+test.fake_logfile('foo-001-2.log', 1)
+
+expect_notitle = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1, \\
+ '-' title "Full build" with lines lt 2, \\
+ '-' title "Up-to-date build" with lines lt 3
+# Startup
+0 4000.000
+1 4001.000
+e
+# Full build
+0 4000.000
+1 4001.000
+e
+# Up-to-date build
+0 4000.000
+1 4001.000
+e
+"""
+
+expect_title = 'set title "TITLE"\n' + expect_notitle
+
+test.run(arguments = 'mem --fmt gnuplot', stdout=expect_notitle)
+
+test.run(arguments = 'mem --fmt=gnuplot --title TITLE', stdout=expect_title)
+
+test.run(arguments = 'mem --format gnuplot --title TITLE', stdout=expect_title)
+
+test.run(arguments = 'mem --format=gnuplot', stdout=expect_notitle)
+
+test.pass_test()
diff --git a/test/scons-time/mem/glob.py b/test/scons-time/mem/glob.py
new file mode 100644
index 0000000..6f5174f
--- /dev/null
+++ b/test/scons-time/mem/glob.py
@@ -0,0 +1,52 @@
+#!/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__"
+
+"""
+Verify that the mem subommand globs for files.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+lines = [
+ ' pre-read post-read pre-build post-build\n'
+]
+
+line_fmt = ' 1000 2000 3000 4000 %s\n'
+
+for i in xrange(9):
+ logfile_name = 'foo-%s.log' % i
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % logfile_name)
+
+expect = ''.join(lines)
+
+test.run(arguments = 'mem foo-*.log', stdout = expect)
+
+test.run(arguments = 'mem foo-?.log', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/mem/help.py b/test/scons-time/mem/help.py
new file mode 100644
index 0000000..0658d5b
--- /dev/null
+++ b/test/scons-time/mem/help.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify the "mem" subcommand help.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = [
+ "Usage: scons-time mem [OPTIONS] FILE [...]\n",
+ " -C DIR, --chdir=DIR Change to DIR before looking for files\n",
+ " -h, --help Print this help and exit\n",
+]
+
+test.run(arguments = 'mem -h')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'mem -?')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'mem --help')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'help mem')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.pass_test()
diff --git a/test/scons-time/mem/no-args.py b/test/scons-time/mem/no-args.py
new file mode 100644
index 0000000..cb47c9b
--- /dev/null
+++ b/test/scons-time/mem/no-args.py
@@ -0,0 +1,43 @@
+#!/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__"
+
+"""
+Verify the error when no arguments are specified to the mem subcommand.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = """\
+scons-time: mem: No arguments specified.
+ No *.log files found in "%s".
+ Type "scons-time help mem" for help.
+""" % test.workpath()
+
+test.run(arguments = 'mem', status = 1, stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/mem/prefix.py b/test/scons-time/mem/prefix.py
new file mode 100644
index 0000000..41eb4e4
--- /dev/null
+++ b/test/scons-time/mem/prefix.py
@@ -0,0 +1,62 @@
+#!/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__"
+
+"""
+Verify that the mem -p and --prefix options specify what log files to use.
+"""
+
+import os.path
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.subdir('logs')
+
+header = ' pre-read post-read pre-build post-build\n'
+
+line_fmt = ' 1000 2000 3000 4000 %s\n'
+
+foo_lines = [ header ]
+bar_lines = [ header ]
+
+for i in xrange(3):
+ logfile_name = os.path.join('foo-%s.log' % i)
+ test.fake_logfile(logfile_name)
+ foo_lines.append(line_fmt % logfile_name)
+
+ logfile_name = os.path.join('bar-%s.log' % i)
+ test.fake_logfile(logfile_name)
+ bar_lines.append(line_fmt % logfile_name)
+
+foo_expect = ''.join(foo_lines)
+bar_expect = ''.join(bar_lines)
+
+test.run(arguments = 'mem -p bar', stdout = bar_expect)
+
+test.run(arguments = 'mem --prefix=foo', stdout = foo_expect)
+
+test.pass_test()
diff --git a/test/scons-time/mem/stage.py b/test/scons-time/mem/stage.py
new file mode 100644
index 0000000..88b21e2
--- /dev/null
+++ b/test/scons-time/mem/stage.py
@@ -0,0 +1,83 @@
+#!/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__"
+
+"""
+Verify the mem --stage option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-000-0.log', 0)
+test.fake_logfile('foo-000-1.log', 0)
+test.fake_logfile('foo-000-2.log', 0)
+
+test.fake_logfile('foo-001-0.log', 1)
+test.fake_logfile('foo-001-1.log', 1)
+test.fake_logfile('foo-001-2.log', 1)
+
+expect = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1, \\
+ '-' title "Full build" with lines lt 2, \\
+ '-' title "Up-to-date build" with lines lt 3
+# Startup
+0 %(index)s000.000
+1 %(index)s001.000
+e
+# Full build
+0 %(index)s000.000
+1 %(index)s001.000
+e
+# Up-to-date build
+0 %(index)s000.000
+1 %(index)s001.000
+e
+"""
+
+pre_read = expect % {'index' : 1}
+post_read = expect % {'index' : 2}
+pre_build = expect % {'index' : 3}
+post_build = expect % {'index' : 4}
+
+test.run(arguments = 'mem --fmt gnuplot --stage pre-read', stdout=pre_read)
+
+test.run(arguments = 'mem --fmt gnuplot --stage=post-read', stdout=post_read)
+
+test.run(arguments = 'mem --fmt gnuplot --stage=pre-build', stdout=pre_build)
+
+test.run(arguments = 'mem --fmt gnuplot --stage post-build', stdout=post_build)
+
+expect = """\
+scons-time: mem: Unrecognized stage "unknown".
+"""
+
+test.run(arguments = 'mem --fmt gnuplot --stage unknown',
+ status = 1,
+ stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/mem/tail.py b/test/scons-time/mem/tail.py
new file mode 100644
index 0000000..e2c7ede
--- /dev/null
+++ b/test/scons-time/mem/tail.py
@@ -0,0 +1,55 @@
+#!/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__"
+
+"""
+Verify that the mem subcommand only prints results for the last number
+of files specified with the -t and --tail options.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+
+header = ' pre-read post-read pre-build post-build\n'
+
+lines = []
+
+line_fmt = ' 1000 2000 3000 4000 %s\n'
+
+for i in xrange(9):
+ logfile_name = 'foo-%s.log' % i
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % logfile_name)
+
+expect3 = [header] + lines[-3:]
+expect5 = [header] + lines[-5:]
+
+test.run(arguments = 'mem -t 3 foo-*.log', stdout = ''.join(expect3))
+
+test.run(arguments = 'mem --tail 5 foo-*.log', stdout = ''.join(expect5))
+
+test.pass_test()
diff --git a/test/scons-time/no-args.py b/test/scons-time/no-args.py
new file mode 100644
index 0000000..ba98da2
--- /dev/null
+++ b/test/scons-time/no-args.py
@@ -0,0 +1,42 @@
+#!/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__"
+
+"""
+Verify that invoking scons-test with no arguments prints the
+fall-back message and exits non-zero.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = """\
+Type "scons-time help" for usage.
+"""
+
+test.run(arguments = '', status=1, stderr=expect)
+
+test.pass_test()
diff --git a/test/scons-time/obj/chdir.py b/test/scons-time/obj/chdir.py
new file mode 100644
index 0000000..5e7df89
--- /dev/null
+++ b/test/scons-time/obj/chdir.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify that the obj -C and --chdir options change directory before
+globbing for files.
+"""
+
+import os.path
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.subdir('logs')
+
+lines = [
+ ' pre-read post-read pre-build post-build\n'
+]
+
+line_fmt = ' 1101%(i)s 1102%(i)s 1103%(i)s 1104%(i)s %(logfile_name)s\n'
+
+for i in xrange(9):
+ logfile_name = os.path.join('logs', 'foo-%s.log' % i)
+ test.fake_logfile(logfile_name, i)
+ lines.append(line_fmt % locals())
+
+expect = ''.join(lines)
+
+test.run(arguments = 'obj -C logs Environment.Base foo-*.log', stdout = expect)
+
+test.run(arguments = 'obj --chdir logs Environment.Base foo-?.log', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/obj/file.py b/test/scons-time/obj/file.py
new file mode 100644
index 0000000..c881397
--- /dev/null
+++ b/test/scons-time/obj/file.py
@@ -0,0 +1,71 @@
+#!/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__"
+
+"""
+Verify that config files specified with the -f and --file options
+affect how the obj subcommand processes things.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-001-0.log')
+
+test.fake_logfile('foo-002-0.log')
+
+
+test.write('st1.conf', """\
+prefix = 'foo-001'
+""")
+
+expect1 = """\
+ pre-read post-read pre-build post-build
+ 16010 16020 16030 16040 foo-001-0.log
+"""
+
+test.run(arguments = 'obj -f st1.conf Node.FS.Base', stdout = expect1)
+
+
+test.write('st2.conf', """\
+prefix = 'foo'
+title = 'ST2.CONF TITLE'
+""")
+
+expect2 = \
+r"""set title "ST2.CONF TITLE"
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+1 16040.000
+2 16040.000
+e
+"""
+
+test.run(arguments = 'obj --file st2.conf --fmt gnuplot Node.FS.Base', stdout = expect2)
+
+
+test.pass_test()
diff --git a/test/scons-time/obj/format-gnuplot.py b/test/scons-time/obj/format-gnuplot.py
new file mode 100644
index 0000000..b47d843
--- /dev/null
+++ b/test/scons-time/obj/format-gnuplot.py
@@ -0,0 +1,76 @@
+#!/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__"
+
+"""
+Verify the obj --format=gnuplot option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-000-0.log', 0)
+test.fake_logfile('foo-000-1.log', 0)
+test.fake_logfile('foo-000-2.log', 0)
+
+test.fake_logfile('foo-001-0.log', 1)
+test.fake_logfile('foo-001-1.log', 1)
+test.fake_logfile('foo-001-2.log', 1)
+
+expect_notitle = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1, \\
+ '-' title "Full build" with lines lt 2, \\
+ '-' title "Up-to-date build" with lines lt 3
+# Startup
+0 20040.000
+1 20041.000
+e
+# Full build
+0 20040.000
+1 20041.000
+e
+# Up-to-date build
+0 20040.000
+1 20041.000
+e
+"""
+
+expect_title = 'set title "TITLE"\n' + expect_notitle
+
+test.run(arguments = 'obj --fmt gnuplot Node.Node',
+ stdout=expect_notitle)
+
+test.run(arguments = 'obj --fmt=gnuplot --title TITLE Node.Node',
+ stdout=expect_title)
+
+test.run(arguments = 'obj --format gnuplot --title TITLE Node.Node',
+ stdout=expect_title)
+
+test.run(arguments = 'obj --format=gnuplot Node.Node',
+ stdout=expect_notitle)
+
+test.pass_test()
diff --git a/test/scons-time/obj/glob.py b/test/scons-time/obj/glob.py
new file mode 100644
index 0000000..4af2854
--- /dev/null
+++ b/test/scons-time/obj/glob.py
@@ -0,0 +1,52 @@
+#!/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__"
+
+"""
+Verify that the obj subcommand globs for files.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+lines = [
+ ' pre-read post-read pre-build post-build\n'
+]
+
+line_fmt = ' 601%(i)s 602%(i)s 603%(i)s 604%(i)s %(logfile_name)s\n'
+
+for i in xrange(9):
+ logfile_name = 'foo-%s.log' % i
+ test.fake_logfile(logfile_name, i)
+ lines.append(line_fmt % locals())
+
+expect = ''.join(lines)
+
+test.run(arguments = 'obj Builder.BuilderBase foo-*.log', stdout = expect)
+
+test.run(arguments = 'obj Builder.BuilderBase foo-?.log', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/obj/help.py b/test/scons-time/obj/help.py
new file mode 100644
index 0000000..95abad6
--- /dev/null
+++ b/test/scons-time/obj/help.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify the "obj" subcommand help.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = [
+ "Usage: scons-time obj [OPTIONS] OBJECT FILE [...]\n",
+ " -C DIR, --chdir=DIR Change to DIR before looking for files\n",
+ " -h, --help Print this help and exit\n",
+]
+
+test.run(arguments = 'obj -h')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'obj -?')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'obj --help')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'help obj')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.pass_test()
diff --git a/test/scons-time/obj/no-args.py b/test/scons-time/obj/no-args.py
new file mode 100644
index 0000000..a4d3f84
--- /dev/null
+++ b/test/scons-time/obj/no-args.py
@@ -0,0 +1,42 @@
+#!/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__"
+
+"""
+Verify the error when no arguments are specified to the obj subcommand.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = """\
+scons-time: obj: Must specify an object name.
+ Type "scons-time help obj" for help.
+"""
+
+test.run(arguments = 'obj', status = 1, stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/obj/no-files.py b/test/scons-time/obj/no-files.py
new file mode 100644
index 0000000..cd91ceb
--- /dev/null
+++ b/test/scons-time/obj/no-files.py
@@ -0,0 +1,44 @@
+#!/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__"
+
+"""
+Verify the error when the obj subcommand is passed object argument but no
+file arguments.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = """\
+scons-time: obj: No arguments specified.
+ No *.log files found in "%s".
+ Type "scons-time help obj" for help.
+""" % test.workpath()
+
+test.run(arguments = 'obj fake.object', status = 1, stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/obj/prefix.py b/test/scons-time/obj/prefix.py
new file mode 100644
index 0000000..8005dc4
--- /dev/null
+++ b/test/scons-time/obj/prefix.py
@@ -0,0 +1,62 @@
+#!/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__"
+
+"""
+Verify that the obj -p and --prefix options specify what log files to use.
+"""
+
+import os.path
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.subdir('logs')
+
+header = ' pre-read post-read pre-build post-build\n'
+
+line_fmt = ' 11010 11020 11030 11040 %s\n'
+
+foo_lines = [ header ]
+bar_lines = [ header ]
+
+for i in xrange(3):
+ logfile_name = os.path.join('foo-%s.log' % i)
+ test.fake_logfile(logfile_name)
+ foo_lines.append(line_fmt % logfile_name)
+
+ logfile_name = os.path.join('bar-%s.log' % i)
+ test.fake_logfile(logfile_name)
+ bar_lines.append(line_fmt % logfile_name)
+
+foo_expect = ''.join(foo_lines)
+bar_expect = ''.join(bar_lines)
+
+test.run(arguments = 'obj -p bar Environment.Base', stdout = bar_expect)
+
+test.run(arguments = 'obj --prefix=foo Environment.Base', stdout = foo_expect)
+
+test.pass_test()
diff --git a/test/scons-time/obj/stage.py b/test/scons-time/obj/stage.py
new file mode 100644
index 0000000..5dbd15b
--- /dev/null
+++ b/test/scons-time/obj/stage.py
@@ -0,0 +1,88 @@
+#!/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__"
+
+"""
+Verify the obj --stage option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-000-0.log', 0)
+test.fake_logfile('foo-000-1.log', 0)
+test.fake_logfile('foo-000-2.log', 0)
+
+test.fake_logfile('foo-001-0.log', 1)
+test.fake_logfile('foo-001-1.log', 1)
+test.fake_logfile('foo-001-2.log', 1)
+
+expect = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1, \\
+ '-' title "Full build" with lines lt 2, \\
+ '-' title "Up-to-date build" with lines lt 3
+# Startup
+0 50%(index)s0.000
+1 50%(index)s1.000
+e
+# Full build
+0 50%(index)s0.000
+1 50%(index)s1.000
+e
+# Up-to-date build
+0 50%(index)s0.000
+1 50%(index)s1.000
+e
+"""
+
+pre_read = expect % {'index' : 1}
+post_read = expect % {'index' : 2}
+pre_build = expect % {'index' : 3}
+post_build = expect % {'index' : 4}
+
+test.run(arguments = 'obj --fmt gnuplot --stage pre-read Action.ListAction',
+ stdout=pre_read)
+
+test.run(arguments = 'obj --fmt gnuplot --stage=post-read Action.ListAction',
+ stdout=post_read)
+
+test.run(arguments = 'obj --fmt gnuplot --stage=pre-build Action.ListAction',
+ stdout=pre_build)
+
+test.run(arguments = 'obj --fmt gnuplot --stage post-build Action.ListAction',
+ stdout=post_build)
+
+expect = """\
+scons-time: obj: Unrecognized stage "unknown".
+ Type "scons-time help obj" for help.
+"""
+
+test.run(arguments = 'obj --fmt gnuplot --stage unknown',
+ status = 1,
+ stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/obj/tail.py b/test/scons-time/obj/tail.py
new file mode 100644
index 0000000..0483d89
--- /dev/null
+++ b/test/scons-time/obj/tail.py
@@ -0,0 +1,55 @@
+#!/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__"
+
+"""
+Verify that the obj subcommand only prints results for the last number
+of files specified with the -t and --tail options.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+
+header = ' pre-read post-read pre-build post-build\n'
+
+lines = []
+
+line_fmt = ' 1501%(i)s 1502%(i)s 1503%(i)s 1504%(i)s %(logfile_name)s\n'
+
+for i in xrange(9):
+ logfile_name = 'foo-%s.log' % i
+ test.fake_logfile(logfile_name, i)
+ lines.append(line_fmt % locals())
+
+expect3 = ''.join([header] + lines[-3:])
+expect5 = ''.join([header] + lines[-5:])
+
+test.run(arguments = 'obj -t 3 Node.FS foo-*.log', stdout = expect3)
+
+test.run(arguments = 'obj --tail 5 Node.FS foo-*.log', stdout = expect5)
+
+test.pass_test()
diff --git a/test/scons-time/run/aegis.py b/test/scons-time/run/aegis.py
new file mode 100644
index 0000000..8f378cb
--- /dev/null
+++ b/test/scons-time/run/aegis.py
@@ -0,0 +1,84 @@
+#!/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__"
+
+"""
+Verify the ability to "check out" an SCons delta from a fake
+Aegis utility.
+"""
+
+import re
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_sample_project('foo.tar')
+
+my_aegis_py = test.write_fake_aegis_py('my_aegis.py')
+
+test.write('config', """\
+aegis = r'%(my_aegis_py)s'
+""" % locals())
+
+test.run(arguments = 'run -f config --aegis xyzzy.0.1 --number 321,329 foo.tar')
+
+test.must_exist('foo-321-0.log',
+ 'foo-321-0.prof',
+ 'foo-321-1.log',
+ 'foo-321-1.prof',
+ 'foo-321-2.log',
+ 'foo-321-2.prof')
+
+test.must_exist('foo-329-0.log',
+ 'foo-329-0.prof',
+ 'foo-329-1.log',
+ 'foo-329-1.prof',
+ 'foo-329-2.log',
+ 'foo-329-2.prof')
+
+def tempdir_re(*args):
+ import os
+ import os.path
+ import string
+ import tempfile
+
+ sep = re.escape(os.sep)
+ args = (tempfile.gettempdir(), 'scons-time-aegis-',) + args
+ x = apply(os.path.join, args)
+ x = re.escape(x)
+ x = string.replace(x, 'aegis\\-', 'aegis\\-[^%s]*' % sep)
+ return x
+
+expect = [
+ tempdir_re('src', 'script', 'scons.py'),
+ 'SCONS_LIB_DIR = %s' % tempdir_re('src', 'engine'),
+]
+
+content = test.read(test.workpath('foo-321-2.log'))
+
+test.must_contain_all_lines('foo-617-2.log', content, expect, re.search)
+
+test.pass_test()
diff --git a/test/scons-time/run/archive/dir.py b/test/scons-time/run/archive/dir.py
new file mode 100644
index 0000000..a6c48ec
--- /dev/null
+++ b/test/scons-time/run/archive/dir.py
@@ -0,0 +1,49 @@
+#!/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__"
+
+"""
+Verify basic generation of timing information from an input fake-project
+directory tree.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo')
+
+test.run(arguments = 'run foo')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/archive/tar-gz.py b/test/scons-time/run/archive/tar-gz.py
new file mode 100644
index 0000000..ac69e29
--- /dev/null
+++ b/test/scons-time/run/archive/tar-gz.py
@@ -0,0 +1,49 @@
+#!/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__"
+
+"""
+Verify basic generation of timing information from an input fake-project
+.tar.gz file.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.run(arguments = 'run foo.tar.gz')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/archive/tar.py b/test/scons-time/run/archive/tar.py
new file mode 100644
index 0000000..18823d7
--- /dev/null
+++ b/test/scons-time/run/archive/tar.py
@@ -0,0 +1,49 @@
+#!/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__"
+
+"""
+Verify basic generation of timing information from an input fake-project
+.tar file.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar')
+
+test.run(arguments = 'run foo.tar')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/archive/tgz.py b/test/scons-time/run/archive/tgz.py
new file mode 100644
index 0000000..f7df9a0
--- /dev/null
+++ b/test/scons-time/run/archive/tgz.py
@@ -0,0 +1,49 @@
+#!/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__"
+
+"""
+Verify basic generation of timing information from an input fake-project
+.tgz file.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tgz')
+
+test.run(arguments = 'run foo.tgz')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/archive/zip.py b/test/scons-time/run/archive/zip.py
new file mode 100644
index 0000000..67cfc3a
--- /dev/null
+++ b/test/scons-time/run/archive/zip.py
@@ -0,0 +1,49 @@
+#!/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__"
+
+"""
+Verify basic generation of timing information from an input fake-project
+.zip file.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.zip')
+
+test.run(arguments = 'run foo.zip')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/config/archive_list.py b/test/scons-time/run/config/archive_list.py
new file mode 100644
index 0000000..8d48d26
--- /dev/null
+++ b/test/scons-time/run/config/archive_list.py
@@ -0,0 +1,73 @@
+#!/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__"
+
+"""
+Verify specifying a list of archives through the archive_list setting
+in a config file.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.write('config', """\
+archive_list = ['foo.tar.gz']
+""")
+
+test.run(arguments = 'run -f config')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+
+test.write_sample_project('bar.tar.gz')
+
+test.run(arguments = 'run -f config bar.tar.gz')
+
+test.must_not_exist('foo-001-0.log',
+ 'foo-001-0.prof',
+ 'foo-001-1.log',
+ 'foo-001-1.prof',
+ 'foo-001-2.log',
+ 'foo-001-2.prof')
+
+test.must_exist('bar-000-0.log',
+ 'bar-000-0.prof',
+ 'bar-000-1.log',
+ 'bar-000-1.prof',
+ 'bar-000-2.log',
+ 'bar-000-2.prof')
+
+
+test.pass_test()
diff --git a/test/scons-time/run/config/initial_commands.py b/test/scons-time/run/config/initial_commands.py
new file mode 100644
index 0000000..73328ef
--- /dev/null
+++ b/test/scons-time/run/config/initial_commands.py
@@ -0,0 +1,56 @@
+#!/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__"
+
+"""
+Verify specifying a list of initial commands through a config file.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.write('config', """\
+def touch(arg):
+ open(arg, 'w')
+initial_commands = [(touch, 'touch %%%%s', r'%s')]
+""" % test.workpath('INITIAL'))
+
+test.run(arguments = 'run -f config foo.tar.gz')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+test.must_exist('INITIAL')
+
+test.pass_test()
diff --git a/test/scons-time/run/config/prefix.py b/test/scons-time/run/config/prefix.py
new file mode 100644
index 0000000..c04c9e7
--- /dev/null
+++ b/test/scons-time/run/config/prefix.py
@@ -0,0 +1,52 @@
+#!/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__"
+
+"""
+Verify specifying an alternate file prefix through a config file.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.write('config', """\
+prefix = 'bar'
+""")
+
+test.run(arguments = 'run -f config foo.tar.gz')
+
+test.must_exist('bar-000-0.log',
+ 'bar-000-0.prof',
+ 'bar-000-1.log',
+ 'bar-000-1.prof',
+ 'bar-000-2.log',
+ 'bar-000-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/config/python.py b/test/scons-time/run/config/python.py
new file mode 100644
index 0000000..4aa85b4
--- /dev/null
+++ b/test/scons-time/run/config/python.py
@@ -0,0 +1,68 @@
+#!/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__"
+
+"""
+Verify specifying an alternate Python executable in a config file.
+"""
+
+import os
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_sample_project('foo.tar.gz')
+
+my_python_py = test.workpath('my_python.py')
+
+test.write('config', """\
+python = r'%(my_python_py)s'
+""" % locals())
+
+test.write(my_python_py, """\
+#!/usr/bin/env python
+import sys
+profile = ''
+for arg in sys.argv[1:]:
+ if arg.startswith('--profile='):
+ profile = arg[10:]
+ break
+print 'my_python.py: %s' % profile
+""")
+
+os.chmod(my_python_py, 0755)
+
+test.run(arguments = 'run -f config foo.tar.gz')
+
+prof0 = test.workpath('foo-000-0.prof')
+prof1 = test.workpath('foo-000-1.prof')
+prof2 = test.workpath('foo-000-2.prof')
+
+test.must_match('foo-000-0.log', "my_python.py: %s\n" % prof0)
+test.must_match('foo-000-1.log', "my_python.py: %s\n" % prof1)
+test.must_match('foo-000-2.log', "my_python.py: %s\n" % prof2)
+
+test.pass_test()
diff --git a/test/scons-time/run/config/scons.py b/test/scons-time/run/config/scons.py
new file mode 100644
index 0000000..45ca369
--- /dev/null
+++ b/test/scons-time/run/config/scons.py
@@ -0,0 +1,65 @@
+#!/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__"
+
+"""
+Verify specifying an alternate SCons through a config file.
+"""
+
+import os
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_sample_project('foo.tar.gz')
+
+my_scons_py = test.workpath('my_scons.py')
+
+test.write('config', """\
+scons = r'%(my_scons_py)s'
+""" % locals())
+
+test.write(my_scons_py, """\
+import sys
+profile = ''
+for arg in sys.argv[1:]:
+ if arg.startswith('--profile='):
+ profile = arg[10:]
+ break
+print 'my_scons.py: %s' % profile
+""")
+
+test.run(arguments = 'run -f config foo.tar.gz')
+
+prof0 = test.workpath('foo-000-0.prof')
+prof1 = test.workpath('foo-000-1.prof')
+prof2 = test.workpath('foo-000-2.prof')
+
+test.must_match('foo-000-0.log', "my_scons.py: %s\n" % prof0)
+test.must_match('foo-000-1.log', "my_scons.py: %s\n" % prof1)
+test.must_match('foo-000-2.log', "my_scons.py: %s\n" % prof2)
+
+test.pass_test()
diff --git a/test/scons-time/run/config/subdir.py b/test/scons-time/run/config/subdir.py
new file mode 100644
index 0000000..4d21318
--- /dev/null
+++ b/test/scons-time/run/config/subdir.py
@@ -0,0 +1,63 @@
+#!/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__"
+
+"""
+Verify picking up the subdir value from a config file.
+"""
+
+import os
+import re
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz', 'subdir')
+
+test.write('config', """\
+subdir = 'subdir'
+""")
+
+test.run(arguments = 'run -f config foo.tar.gz')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+content = test.read(test.workpath('foo-000-0.log'), mode='r')
+
+expect = [
+ 'SConstruct file directory: .*%ssubdir$' % re.escape(os.sep),
+]
+
+test.must_contain_all_lines('foo-000-0.log', content, expect, re.search)
+
+test.pass_test()
diff --git a/test/scons-time/run/config/targets.py b/test/scons-time/run/config/targets.py
new file mode 100644
index 0000000..8d2abd1
--- /dev/null
+++ b/test/scons-time/run/config/targets.py
@@ -0,0 +1,86 @@
+#!/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__"
+
+"""
+Verify specifying a list of targets through a config file.
+"""
+
+import os
+import re
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.write('config', """\
+targets = 'target1 target2'
+""")
+
+test.run(arguments = 'run -f config foo.tar.gz')
+
+scons_py = re.escape(test.workpath('src', 'script', 'scons.py'))
+src_engine = re.escape(test.workpath('src', 'engine'))
+
+prof1 = re.escape(test.workpath('foo-000-1.prof'))
+prof2 = re.escape(test.workpath('foo-000-2.prof'))
+
+sep = re.escape(os.sep)
+
+expect = """\
+%(scons_py)s
+ --debug=count
+ --debug=memory
+ --debug=time
+ --debug=memoizer
+ --profile=%(prof1)s
+ target1
+ target2
+SCONS_LIB_DIR = %(src_engine)s
+SConstruct file directory: .*scons-time-.*%(sep)sfoo
+""" % locals()
+
+test.must_match('foo-000-1.log', expect, mode='r')
+
+expect = """\
+%(scons_py)s
+ --debug=count
+ --debug=memory
+ --debug=time
+ --debug=memoizer
+ --profile=%(prof2)s
+ target1
+ target2
+SCONS_LIB_DIR = %(src_engine)s
+SConstruct file directory: .*scons-time-.*%(sep)sfoo
+""" % locals()
+
+test.must_match('foo-000-2.log', expect, mode='r')
+
+test.pass_test()
diff --git a/test/scons-time/run/option/help.py b/test/scons-time/run/option/help.py
new file mode 100644
index 0000000..304992f
--- /dev/null
+++ b/test/scons-time/run/option/help.py
@@ -0,0 +1,59 @@
+#!/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__"
+
+"""
+Verify that the run -h option (and variants) prints help.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = [
+ "Usage: scons-time run [OPTIONS] [FILE ...]\n",
+ " -h, --help Print this help and exit\n",
+ " -n, --no-exec No execute, just print command lines\n",
+ " -q, --quiet Don't print command lines\n",
+ " -v, --verbose Display output of commands\n",
+]
+
+test.run(arguments = 'run -h')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'run -?')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'run --help')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'help run')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.pass_test()
diff --git a/test/scons-time/run/option/next-run.py b/test/scons-time/run/option/next-run.py
new file mode 100644
index 0000000..8a23939
--- /dev/null
+++ b/test/scons-time/run/option/next-run.py
@@ -0,0 +1,99 @@
+#!/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__"
+
+"""
+Verify that the script finds the next run number based on the
+contents of the directory, even when specified with --outdir.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.subdir('sub')
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.run(arguments = 'run foo.tar.gz')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+test.must_not_exist('foo-001-0.log',
+ 'foo-001-0.prof',
+ 'foo-001-1.log',
+ 'foo-001-1.prof',
+ 'foo-001-2.log',
+ 'foo-001-2.prof')
+
+test.run(arguments = 'run foo.tar.gz')
+
+test.must_exist('foo-001-0.log',
+ 'foo-001-0.prof',
+ 'foo-001-1.log',
+ 'foo-001-1.prof',
+ 'foo-001-2.log',
+ 'foo-001-2.prof')
+
+test.must_not_exist('foo-002-0.log',
+ 'foo-002-0.prof',
+ 'foo-002-1.log',
+ 'foo-002-1.prof',
+ 'foo-002-2.log',
+ 'foo-002-2.prof')
+
+test.run(arguments = 'run foo.tar.gz')
+
+test.must_exist('foo-002-0.log',
+ 'foo-002-0.prof',
+ 'foo-002-1.log',
+ 'foo-002-1.prof',
+ 'foo-002-2.log',
+ 'foo-002-2.prof')
+
+test.run(arguments = 'run --outdir sub foo.tar.gz')
+
+test.must_exist(['sub', 'foo-000-0.log'],
+ ['sub', 'foo-000-0.prof'],
+ ['sub', 'foo-000-1.log'],
+ ['sub', 'foo-000-1.prof'],
+ ['sub', 'foo-000-2.log'],
+ ['sub', 'foo-000-2.prof'])
+
+test.must_not_exist('foo-003-0.log',
+ 'foo-003-0.prof',
+ 'foo-003-1.log',
+ 'foo-003-1.prof',
+ 'foo-003-2.log',
+ 'foo-003-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/option/no-args.py b/test/scons-time/run/option/no-args.py
new file mode 100644
index 0000000..520b27d
--- /dev/null
+++ b/test/scons-time/run/option/no-args.py
@@ -0,0 +1,42 @@
+#!/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__"
+
+"""
+Verify the error when the run command is passed no arguments.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = """\
+scons-time: run: No arguments or -f config file specified.
+ Type "scons-time help run" for help.
+"""
+
+test.run(arguments = 'run', status = 1, stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/run/option/no-exec.py b/test/scons-time/run/option/no-exec.py
new file mode 100644
index 0000000..a2eab74
--- /dev/null
+++ b/test/scons-time/run/option/no-exec.py
@@ -0,0 +1,49 @@
+#!/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__"
+
+"""
+Verify that the run -n and --no-exec options don't actually create the
+expected output files.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_sample_project('foo.tar.gz')
+
+test.run(arguments = 'run -n foo.tar.gz')
+
+test.run(arguments = 'run --no-exec foo.tar.gz')
+
+test.must_not_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/option/number.py b/test/scons-time/run/option/number.py
new file mode 100644
index 0000000..ddf2d86
--- /dev/null
+++ b/test/scons-time/run/option/number.py
@@ -0,0 +1,48 @@
+#!/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__"
+
+"""
+Verify the run --number option specifies the run number.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.run(arguments = 'run --number 77 foo.tar.gz')
+
+test.must_exist('foo-077-0.log',
+ 'foo-077-0.prof',
+ 'foo-077-1.log',
+ 'foo-077-1.prof',
+ 'foo-077-2.log',
+ 'foo-077-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/option/outdir.py b/test/scons-time/run/option/outdir.py
new file mode 100644
index 0000000..f60eba0
--- /dev/null
+++ b/test/scons-time/run/option/outdir.py
@@ -0,0 +1,51 @@
+
+#!/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__"
+
+"""
+Verify specifying an alternate output directory with the --outdir option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.subdir('sub')
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.run(arguments = 'run --outdir sub foo.tar.gz')
+
+test.must_exist(['sub', 'foo-000-0.log'],
+ ['sub', 'foo-000-0.prof'],
+ ['sub', 'foo-000-1.log'],
+ ['sub', 'foo-000-1.prof'],
+ ['sub', 'foo-000-2.log'],
+ ['sub', 'foo-000-2.prof'])
+
+test.pass_test()
diff --git a/test/scons-time/run/option/prefix.py b/test/scons-time/run/option/prefix.py
new file mode 100644
index 0000000..6bc9619
--- /dev/null
+++ b/test/scons-time/run/option/prefix.py
@@ -0,0 +1,48 @@
+#!/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__"
+
+"""
+Verify specifying an alternate file prefix with the --prefix option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz')
+
+test.run(arguments = 'run --prefix bar foo.tar.gz')
+
+test.must_exist('bar-000-0.log',
+ 'bar-000-0.prof',
+ 'bar-000-1.log',
+ 'bar-000-1.prof',
+ 'bar-000-2.log',
+ 'bar-000-2.prof')
+
+test.pass_test()
diff --git a/test/scons-time/run/option/python.py b/test/scons-time/run/option/python.py
new file mode 100644
index 0000000..bd12efe
--- /dev/null
+++ b/test/scons-time/run/option/python.py
@@ -0,0 +1,64 @@
+#!/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__"
+
+"""
+Verify the run --python option to specify an alternatie Python executable.
+"""
+
+import os
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_sample_project('foo.tar.gz')
+
+my_python_py = test.workpath('my_python.py')
+
+test.write(my_python_py, """\
+#!/usr/bin/env python
+import sys
+profile = ''
+for arg in sys.argv[1:]:
+ if arg.startswith('--profile='):
+ profile = arg[10:]
+ break
+sys.stdout.write('my_python.py: %s\\n' % profile)
+""")
+
+os.chmod(my_python_py, 0755)
+
+test.run(arguments = 'run --python %s foo.tar.gz' % my_python_py)
+
+prof0 = test.workpath('foo-000-0.prof')
+prof1 = test.workpath('foo-000-1.prof')
+prof2 = test.workpath('foo-000-2.prof')
+
+test.must_match('foo-000-0.log', "my_python.py: %s\n" % prof0)
+test.must_match('foo-000-1.log', "my_python.py: %s\n" % prof1)
+test.must_match('foo-000-2.log', "my_python.py: %s\n" % prof2)
+
+test.pass_test()
diff --git a/test/scons-time/run/option/quiet.py b/test/scons-time/run/option/quiet.py
new file mode 100644
index 0000000..5d5d7cf
--- /dev/null
+++ b/test/scons-time/run/option/quiet.py
@@ -0,0 +1,96 @@
+#!/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__"
+
+"""
+Verify that the run -q and --quiet options suppress build output.
+"""
+
+import re
+
+import TestSCons_time
+
+python = TestSCons_time.python
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+test.diff_function = TestSCons_time.diff_re
+
+
+def tempdir_re(*args):
+ import os
+ import os.path
+ import string
+ import tempfile
+
+ sep = re.escape(os.sep)
+ args = (tempfile.gettempdir(), 'scons-time-',) + args
+ x = apply(os.path.join, args)
+ x = re.escape(x)
+ x = string.replace(x, 'time\\-', 'time\\-[^%s]*' % sep)
+ return x
+
+scons_py = re.escape(test.workpath('src', 'script', 'scons.py'))
+src_engine = re.escape(test.workpath('src', 'engine'))
+
+tmp_scons_time = tempdir_re()
+tmp_scons_time_foo = tempdir_re('foo')
+
+
+test.write_fake_scons_py()
+
+foo_tar_gz = test.write_sample_project('foo.tar.gz')
+
+expect = """\
+%(scons_py)s
+ --version
+SCONS_LIB_DIR = %(src_engine)s
+SConstruct file directory: %(tmp_scons_time_foo)s
+""" % locals()
+
+test.run(arguments = 'run -q foo.tar.gz', stdout = expect)
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+scons_py = test.workpath('src/script/scons.py')
+
+src_engine = test.workpath('src/engine')
+
+test.run(arguments = 'run -q foo.tar.gz', stdout = expect)
+
+test.must_exist('foo-001-0.log',
+ 'foo-001-0.prof',
+ 'foo-001-1.log',
+ 'foo-001-1.prof',
+ 'foo-001-2.log',
+ 'foo-001-2.prof')
+
+test.run(arguments = 'run --quiet foo.tar.gz', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/run/option/scons.py b/test/scons-time/run/option/scons.py
new file mode 100644
index 0000000..14ac18d
--- /dev/null
+++ b/test/scons-time/run/option/scons.py
@@ -0,0 +1,59 @@
+#!/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__"
+
+"""
+Verify the run --scons option to specify an alternatie SCons script.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_sample_project('foo.tar.gz')
+
+my_scons_py = test.workpath('my_scons.py')
+
+test.write(my_scons_py, """\
+import sys
+profile = ''
+for arg in sys.argv[1:]:
+ if arg.startswith('--profile='):
+ profile = arg[10:]
+ break
+print 'my_scons.py: %s' % profile
+""")
+
+test.run(arguments = 'run --scons %s foo.tar.gz' % my_scons_py)
+
+prof0 = test.workpath('foo-000-0.prof')
+prof1 = test.workpath('foo-000-1.prof')
+prof2 = test.workpath('foo-000-2.prof')
+
+test.must_match('foo-000-0.log', "my_scons.py: %s\n" % prof0)
+test.must_match('foo-000-1.log', "my_scons.py: %s\n" % prof1)
+test.must_match('foo-000-2.log', "my_scons.py: %s\n" % prof2)
+
+test.pass_test()
diff --git a/test/scons-time/run/option/subdir.py b/test/scons-time/run/option/subdir.py
new file mode 100644
index 0000000..b96d0e6
--- /dev/null
+++ b/test/scons-time/run/option/subdir.py
@@ -0,0 +1,59 @@
+#!/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__"
+
+"""
+Verify that we change to a subdirectory before building if asked to do so.
+"""
+
+import os
+import re
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_fake_scons_py()
+
+test.write_sample_project('foo.tar.gz', 'subdir')
+
+test.run(arguments = 'run --subdir subdir foo.tar.gz')
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+expect = [
+ 'SConstruct file directory: .*%ssubdir$' % re.escape(os.sep),
+]
+
+content = test.read(test.workpath('foo-000-0.log'), mode='r')
+
+test.must_contain_all_lines('foo-000-0.log', content, expect, re.search)
+
+test.pass_test()
diff --git a/test/scons-time/run/option/verbose.py b/test/scons-time/run/option/verbose.py
new file mode 100644
index 0000000..cdf5b5a
--- /dev/null
+++ b/test/scons-time/run/option/verbose.py
@@ -0,0 +1,161 @@
+#!/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__"
+
+"""
+Verify that the run -v and --verbose options display command output.
+"""
+
+import re
+
+import TestSCons_time
+
+_python_ = re.escape(TestSCons_time._python_)
+
+
+test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+test.diff_function = TestSCons_time.diff_re
+
+
+def tempdir_re(*args):
+ import os
+ import os.path
+ import string
+ import tempfile
+
+ sep = re.escape(os.sep)
+ args = (tempfile.gettempdir(), 'scons-time-',) + args
+ x = apply(os.path.join, args)
+ x = re.escape(x)
+ x = string.replace(x, 'time\\-', 'time\\-[^%s]*' % sep)
+ return x
+
+scons_py = re.escape(test.workpath('src', 'script', 'scons.py'))
+src_engine = re.escape(test.workpath('src', 'engine'))
+
+tmp_scons_time = tempdir_re()
+tmp_scons_time_foo = tempdir_re('foo')
+
+
+test.write_fake_scons_py()
+
+foo_tar_gz = test.write_sample_project('foo.tar.gz')
+
+expect = """\
+%(scons_py)s
+ --version
+SCONS_LIB_DIR = %(src_engine)s
+SConstruct file directory: %(tmp_scons_time_foo)s
+""" % locals()
+
+test.run(arguments = 'run -q foo.tar.gz', stdout = expect)
+
+test.must_exist('foo-000-0.log',
+ 'foo-000-0.prof',
+ 'foo-000-1.log',
+ 'foo-000-1.prof',
+ 'foo-000-2.log',
+ 'foo-000-2.prof')
+
+time_re = r'\[\d\d:\d\d:\d\d\]'
+
+scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer'
+
+
+expect = """\
+scons-time%(time_re)s: mkdir %(tmp_scons_time)s
+scons-time%(time_re)s: cd %(tmp_scons_time)s
+scons-time%(time_re)s: tar xzf %(foo_tar_gz)s
+scons-time%(time_re)s: cd foo
+scons-time%(time_re)s: find \\* -type f | xargs cat > /dev/null
+scons-time%(time_re)s: export SCONS_LIB_DIR=%(src_engine)s
+scons-time%(time_re)s: %(_python_)s %(scons_py)s --version
+%(scons_py)s
+ --version
+SCONS_LIB_DIR = %(src_engine)s
+SConstruct file directory: %(tmp_scons_time_foo)s
+scons-time%(time_re)s: %(_python_)s %(scons_py)s %(scons_flags)s --profile=%(prof0)s --help 2>&1 \\| tee %(log0)s
+%(scons_py)s
+ --debug=count
+ --debug=memory
+ --debug=time
+ --debug=memoizer
+ --profile=%(prof0)s
+ --help
+SCONS_LIB_DIR = %(src_engine)s
+SConstruct file directory: %(tmp_scons_time_foo)s
+scons-time%(time_re)s: %(_python_)s %(scons_py)s %(scons_flags)s --profile=%(prof1)s 2>&1 \\| tee %(log1)s
+%(scons_py)s
+ --debug=count
+ --debug=memory
+ --debug=time
+ --debug=memoizer
+ --profile=%(prof1)s
+SCONS_LIB_DIR = %(src_engine)s
+SConstruct file directory: %(tmp_scons_time_foo)s
+scons-time%(time_re)s: %(_python_)s %(scons_py)s %(scons_flags)s --profile=%(prof2)s 2>&1 \\| tee %(log2)s
+%(scons_py)s
+ --debug=count
+ --debug=memory
+ --debug=time
+ --debug=memoizer
+ --profile=%(prof2)s
+SCONS_LIB_DIR = %(src_engine)s
+SConstruct file directory: %(tmp_scons_time_foo)s
+scons-time%(time_re)s: cd .*
+scons-time%(time_re)s: rm -rf %(tmp_scons_time)s
+"""
+
+foo_tar_gz = re.escape(foo_tar_gz)
+
+log0 = re.escape(test.workpath('foo-001-0.log'))
+log1 = re.escape(test.workpath('foo-001-1.log'))
+log2 = re.escape(test.workpath('foo-001-2.log'))
+
+prof0 = re.escape(test.workpath('foo-001-0.prof'))
+prof1 = re.escape(test.workpath('foo-001-1.prof'))
+prof2 = re.escape(test.workpath('foo-001-2.prof'))
+
+test.run(arguments = 'run -v foo.tar.gz', stdout = expect % locals())
+
+test.must_exist('foo-001-0.log',
+ 'foo-001-0.prof',
+ 'foo-001-1.log',
+ 'foo-001-1.prof',
+ 'foo-001-2.log',
+ 'foo-001-2.prof')
+
+log0 = re.escape(test.workpath('foo-002-0.log'))
+log1 = re.escape(test.workpath('foo-002-1.log'))
+log2 = re.escape(test.workpath('foo-002-2.log'))
+
+prof0 = re.escape(test.workpath('foo-002-0.prof'))
+prof1 = re.escape(test.workpath('foo-002-1.prof'))
+prof2 = re.escape(test.workpath('foo-002-2.prof'))
+
+test.run(arguments = 'run --verbose foo.tar.gz', stdout = expect % locals())
+
+
+test.pass_test()
diff --git a/test/scons-time/run/subversion.py b/test/scons-time/run/subversion.py
new file mode 100644
index 0000000..3839999
--- /dev/null
+++ b/test/scons-time/run/subversion.py
@@ -0,0 +1,85 @@
+#!/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__"
+
+"""
+Verify ability to "check out" an SCons revision from a fake
+Subversion utility.
+"""
+
+import re
+import tempfile
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.write_sample_project('foo.tar')
+
+my_svn_py = test.write_fake_svn_py('my_svn.py')
+
+test.write('config', """\
+svn = r'%(my_svn_py)s'
+""" % locals())
+
+test.run(arguments = 'run -f config --svn http://xyzzy --number 617,716 foo.tar')
+
+test.must_exist('foo-617-0.log',
+ 'foo-617-0.prof',
+ 'foo-617-1.log',
+ 'foo-617-1.prof',
+ 'foo-617-2.log',
+ 'foo-617-2.prof')
+
+test.must_exist('foo-716-0.log',
+ 'foo-716-0.prof',
+ 'foo-716-1.log',
+ 'foo-716-1.prof',
+ 'foo-716-2.log',
+ 'foo-716-2.prof')
+
+def tempdir_re(*args):
+ import os
+ import os.path
+ import string
+ import tempfile
+
+ sep = re.escape(os.sep)
+ args = (tempfile.gettempdir(), 'scons-time-svn-',) + args
+ x = apply(os.path.join, args)
+ x = re.escape(x)
+ x = string.replace(x, 'svn\\-', 'svn\\-[^%s]*' % sep)
+ return x
+
+expect = [
+ tempdir_re('src', 'script', 'scons.py'),
+ 'SCONS_LIB_DIR = %s' % tempdir_re('src', 'engine'),
+]
+
+content = test.read(test.workpath('foo-617-2.log'), mode='r')
+
+test.must_contain_all_lines('foo-617-2.log', content, expect, re.search)
+
+test.pass_test()
diff --git a/test/scons-time/time/chdir.py b/test/scons-time/time/chdir.py
new file mode 100644
index 0000000..b2a4d07
--- /dev/null
+++ b/test/scons-time/time/chdir.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify that the time -C and --chdir options change directory before
+globbing for files.
+"""
+
+import os.path
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.subdir('logs')
+
+lines = [
+ ' Total SConscripts SCons commands\n'
+]
+
+line_fmt = ' 11.123456 22.234567 33.345678 44.456789 %s\n'
+
+for i in xrange(9):
+ logfile_name = os.path.join('logs', 'foo-%s.log' % i)
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % logfile_name)
+
+expect = ''.join(lines)
+
+test.run(arguments = 'time -C logs foo-*.log', stdout = expect)
+
+test.run(arguments = 'time --chdir logs foo-?.log', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/time/file.py b/test/scons-time/time/file.py
new file mode 100644
index 0000000..f4046c9
--- /dev/null
+++ b/test/scons-time/time/file.py
@@ -0,0 +1,71 @@
+#!/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__"
+
+"""
+Verify that config files specified with the -f and --file options
+affect how the time subcommand processes things.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-001-0.log')
+
+test.fake_logfile('foo-002-0.log')
+
+
+test.write('st1.conf', """\
+prefix = 'foo-001'
+""")
+
+expect1 = """\
+ Total SConscripts SCons commands
+ 11.123456 22.234567 33.345678 44.456789 foo-001-0.log
+"""
+
+test.run(arguments = 'time -f st1.conf', stdout = expect1)
+
+
+test.write('st2.conf', """\
+prefix = 'foo'
+title = 'ST2.CONF TITLE'
+""")
+
+expect2 = \
+r"""set title "ST2.CONF TITLE"
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+1 11.123456
+2 11.123456
+e
+"""
+
+test.run(arguments = 'time --file st2.conf --fmt gnuplot', stdout = expect2)
+
+
+test.pass_test()
diff --git a/test/scons-time/time/format-gnuplot.py b/test/scons-time/time/format-gnuplot.py
new file mode 100644
index 0000000..8a599a4
--- /dev/null
+++ b/test/scons-time/time/format-gnuplot.py
@@ -0,0 +1,72 @@
+#!/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__"
+
+"""
+Verify the time --format=gnuplot option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-000-0.log', 0)
+test.fake_logfile('foo-000-1.log', 0)
+test.fake_logfile('foo-000-2.log', 0)
+
+test.fake_logfile('foo-001-0.log', 1)
+test.fake_logfile('foo-001-1.log', 1)
+test.fake_logfile('foo-001-2.log', 1)
+
+expect_notitle = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1, \\
+ '-' title "Full build" with lines lt 2, \\
+ '-' title "Up-to-date build" with lines lt 3
+# Startup
+0 11.123456
+1 11.123456
+e
+# Full build
+0 11.123456
+1 11.123456
+e
+# Up-to-date build
+0 11.123456
+1 11.123456
+e
+"""
+
+expect_title = 'set title "TITLE"\n' + expect_notitle
+
+test.run(arguments = 'time --fmt gnuplot', stdout=expect_notitle)
+
+test.run(arguments = 'time --fmt=gnuplot --title TITLE', stdout=expect_title)
+
+test.run(arguments = 'time --format gnuplot --title TITLE', stdout=expect_title)
+
+test.run(arguments = 'time --format=gnuplot', stdout=expect_notitle)
+
+test.pass_test()
diff --git a/test/scons-time/time/glob.py b/test/scons-time/time/glob.py
new file mode 100644
index 0000000..5bf2ccd
--- /dev/null
+++ b/test/scons-time/time/glob.py
@@ -0,0 +1,52 @@
+#!/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__"
+
+"""
+Verify that the time subcommand globs for files.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+lines = [
+ ' Total SConscripts SCons commands\n'
+]
+
+line_fmt = ' 11.123456 22.234567 33.345678 44.456789 %s\n'
+
+for i in xrange(9):
+ logfile_name = 'foo-%s.log' % i
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % logfile_name)
+
+expect = ''.join(lines)
+
+test.run(arguments = 'time foo-*.log', stdout = expect)
+
+test.run(arguments = 'time foo-?.log', stdout = expect)
+
+test.pass_test()
diff --git a/test/scons-time/time/help.py b/test/scons-time/time/help.py
new file mode 100644
index 0000000..2f7cb67
--- /dev/null
+++ b/test/scons-time/time/help.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify the "time" subcommand help.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = [
+ "Usage: scons-time time [OPTIONS] FILE [...]\n",
+ " -C DIR, --chdir=DIR Change to DIR before looking for files\n",
+ " -h, --help Print this help and exit\n",
+]
+
+test.run(arguments = 'time -h')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'time -?')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'time --help')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.run(arguments = 'help time')
+
+test.must_contain_all_lines('Standard output', test.stdout(), expect)
+
+test.pass_test()
diff --git a/test/scons-time/time/no-args.py b/test/scons-time/time/no-args.py
new file mode 100644
index 0000000..510b1b3
--- /dev/null
+++ b/test/scons-time/time/no-args.py
@@ -0,0 +1,43 @@
+#!/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__"
+
+"""
+Verify the error when the time subcommand is passed no arguments.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = """\
+scons-time: mem: No arguments specified.
+ No *.log files found in "%s".
+ Type "scons-time help mem" for help.
+""" % test.workpath()
+
+test.run(arguments = 'mem', status = 1, stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/time/prefix.py b/test/scons-time/time/prefix.py
new file mode 100644
index 0000000..cf0462a
--- /dev/null
+++ b/test/scons-time/time/prefix.py
@@ -0,0 +1,62 @@
+#!/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__"
+
+"""
+Verify that the time -p and --prefix options specify what log files to use.
+"""
+
+import os.path
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.subdir('logs')
+
+header = ' Total SConscripts SCons commands\n'
+
+line_fmt = ' 11.123456 22.234567 33.345678 44.456789 %s\n'
+
+foo_lines = [ header ]
+bar_lines = [ header ]
+
+for i in xrange(3):
+ logfile_name = os.path.join('foo-%s.log' % i)
+ test.fake_logfile(logfile_name)
+ foo_lines.append(line_fmt % logfile_name)
+
+ logfile_name = os.path.join('bar-%s.log' % i)
+ test.fake_logfile(logfile_name)
+ bar_lines.append(line_fmt % logfile_name)
+
+foo_expect = ''.join(foo_lines)
+bar_expect = ''.join(bar_lines)
+
+test.run(arguments = 'time -p bar', stdout = bar_expect)
+
+test.run(arguments = 'time --prefix=foo', stdout = foo_expect)
+
+test.pass_test()
diff --git a/test/scons-time/time/tail.py b/test/scons-time/time/tail.py
new file mode 100644
index 0000000..600bbc8
--- /dev/null
+++ b/test/scons-time/time/tail.py
@@ -0,0 +1,55 @@
+#!/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__"
+
+"""
+Verify that the time subcommand only prints results for the last number
+of files specified with the -t and --tail options.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+
+header = ' Total SConscripts SCons commands\n'
+
+lines = []
+
+line_fmt = ' 11.123456 22.234567 33.345678 44.456789 %s\n'
+
+for i in xrange(9):
+ logfile_name = 'foo-%s.log' % i
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % logfile_name)
+
+expect3 = [header] + lines[-3:]
+expect5 = [header] + lines[-5:]
+
+test.run(arguments = 'time -t 3 foo-*.log', stdout = ''.join(expect3))
+
+test.run(arguments = 'time --tail 5 foo-*.log', stdout = ''.join(expect5))
+
+test.pass_test()
diff --git a/test/scons-time/time/which.py b/test/scons-time/time/which.py
new file mode 100644
index 0000000..30ce3a6
--- /dev/null
+++ b/test/scons-time/time/which.py
@@ -0,0 +1,84 @@
+#!/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__"
+
+"""
+Verify the time --which option.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+test.fake_logfile('foo-000-0.log', 0)
+test.fake_logfile('foo-000-1.log', 0)
+test.fake_logfile('foo-000-2.log', 0)
+
+test.fake_logfile('foo-001-0.log', 1)
+test.fake_logfile('foo-001-1.log', 1)
+test.fake_logfile('foo-001-2.log', 1)
+
+expect = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1, \\
+ '-' title "Full build" with lines lt 2, \\
+ '-' title "Up-to-date build" with lines lt 3
+# Startup
+0 %(time)s
+1 %(time)s
+e
+# Full build
+0 %(time)s
+1 %(time)s
+e
+# Up-to-date build
+0 %(time)s
+1 %(time)s
+e
+"""
+
+total = expect % {'time' : 11.123456}
+SConscripts = expect % {'time' : 22.234567}
+SCons = expect % {'time' : 33.345678}
+commands = expect % {'time' : 44.456789}
+
+test.run(arguments = 'time --fmt gnuplot --which total', stdout=total)
+
+test.run(arguments = 'time --fmt gnuplot --which=SConscripts', stdout=SConscripts)
+
+test.run(arguments = 'time --fmt gnuplot --which=SCons', stdout=SCons)
+
+test.run(arguments = 'time --fmt gnuplot --which commands', stdout=commands)
+
+expect = """\
+scons-time: time: Unrecognized timer "unknown".
+ Type "scons-time help time" for help.
+"""
+
+test.run(arguments = 'time --fmt gnuplot --which unknown',
+ status = 1,
+ stderr = expect)
+
+test.pass_test()
diff --git a/test/scons-time/unknown.py b/test/scons-time/unknown.py
new file mode 100644
index 0000000..2fb673f
--- /dev/null
+++ b/test/scons-time/unknown.py
@@ -0,0 +1,45 @@
+#!/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__"
+
+"""
+Verify that invoking scons-test with an unknown argument generates
+the appropriate error message and exits non-zero.
+"""
+
+import os
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+expect = """\
+scons-time: Unknown subcommand "unknown".
+Type "scons-time help" for usage.
+"""
+
+test.run(arguments = 'unknown', status=1, stderr=expect)
+
+test.pass_test()
diff --git a/test/sconsign/script.py b/test/sconsign/script.py
deleted file mode 100644
index 9612560..0000000
--- a/test/sconsign/script.py
+++ /dev/null
@@ -1,602 +0,0 @@
-#!/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__"
-
-import os.path
-import string
-import time
-
-import TestCmd
-import TestSCons
-
-class MyTestSCons(TestSCons.TestSCons):
- # subclass with a method for running the sconsign script
- def __init__(self, *args, **kw):
- try:
- script_dir = os.environ['SCONS_SCRIPT_DIR']
- except KeyError:
- pass
- else:
- os.chdir(script_dir)
- self.script_dir = os.getcwd()
- apply(TestSCons.TestSCons.__init__, (self,)+args, kw)
- self.my_kw = {
- 'interpreter' : TestSCons.python,
- }
- def script_path(self, script):
- return os.path.join(self.script_dir, script)
- def set_sconsign(self, sconsign):
- self.my_kw['program'] = sconsign
- def run_sconsign(self, *args, **kw):
- kw.update(self.my_kw)
- return apply(self.run, args, kw)
-
-test = MyTestSCons(match = TestCmd.match_re)
-
-# Check for the sconsign script before we instantiate TestSCons(),
-# because that will change directory on us.
-if os.path.exists(test.script_path('sconsign.py')):
- sconsign = 'sconsign.py'
-elif os.path.exists(test.script_path('sconsign')):
- sconsign = 'sconsign'
-else:
- print "Can find neither 'sconsign.py' nor 'sconsign' scripts."
- test.no_result()
-
-test.set_sconsign(sconsign)
-
-def sort_match(test, lines, expect):
- lines = string.split(lines, '\n')
- lines.sort()
- expect = string.split(expect, '\n')
- expect.sort()
- return test.match_re(lines, expect)
-
-def re_sep(*args):
- return string.replace(apply(os.path.join, args), '\\', '\\\\')
-
-
-
-test.subdir('work1', ['work1', 'sub1'], ['work1', 'sub2'],
- 'work2', ['work2', 'sub1'], ['work2', 'sub2'])
-
-test.write(['work1', 'SConstruct'], """
-SConsignFile(None)
-env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
-env1.Program('sub1/hello.c')
-env2 = env1.Clone(CPPPATH = ['sub2'])
-env2.Program('sub2/hello.c')
-""")
-
-test.write(['work1', 'sub1', 'hello.c'], r"""\
-#include <stdio.h>
-#include <stdlib.h>
-int
-main(int argc, char *argv[])
-{
- argv[argc++] = "--";
- printf("sub1/hello.c\n");
- exit (0);
-}
-""")
-
-test.write(['work1', 'sub2', 'hello.c'], r"""\
-#include <stdio.h>
-#include <stdlib.h>
-#include <inc1.h>
-#include <inc2.h>
-int
-main(int argc, char *argv[])
-{
- argv[argc++] = "--";
- printf("sub2/goodbye.c\n");
- exit (0);
-}
-""")
-
-test.write(['work1', 'sub2', 'inc1.h'], r"""\
-#define STRING1 "inc1.h"
-""")
-
-test.write(['work1', 'sub2', 'inc2.h'], r"""\
-#define STRING2 "inc2.h"
-""")
-
-test.run(chdir = 'work1', arguments = '--implicit-cache .')
-
-test.run_sconsign(arguments = "work1/sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
-
-test.run_sconsign(arguments = "--raw work1/sub1/.sconsign",
- stdout = """\
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
-""")
-
-test.run_sconsign(arguments = "-v work1/sub1/.sconsign",
- stdout = """\
-hello.exe:
- bsig: \S+
- csig: None
- timestamp: \d+
- size: \d+
- implicit:
- hello.obj: \S+
-hello.obj:
- bsig: \S+
- csig: None
- timestamp: \d+
- size: \d+
- implicit:
- hello.c: \S+
-""")
-
-test.run_sconsign(arguments = "-b -v work1/sub1/.sconsign",
- stdout = """\
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-""")
-
-test.run_sconsign(arguments = "-c -v work1/sub1/.sconsign",
- stdout = """\
-hello.exe:
- csig: None
-hello.obj:
- csig: None
-""")
-
-test.run_sconsign(arguments = "-s -v work1/sub1/.sconsign",
- stdout = """\
-hello.exe:
- size: \d+
-hello.obj:
- size: \d+
-""")
-
-test.run_sconsign(arguments = "-t -v work1/sub1/.sconsign",
- stdout = """\
-hello.exe:
- timestamp: \d+
-hello.obj:
- timestamp: \d+
-""")
-
-test.run_sconsign(arguments = "-e hello.obj work1/sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
-
-test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj work1/sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
-
-# XXX NOT SURE IF THIS IS RIGHT!
-sub2_inc1_h = re_sep('sub2', 'inc1.h')
-sub2_inc2_h = re_sep('sub2', 'inc2.h')
-
-test.run_sconsign(arguments = "work1/sub2/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
-
-#test.run_sconsign(arguments = "-i -v work1/sub2/.sconsign",
-# stdout = """\
-#hello.exe:
-# implicit:
-# hello.obj: \S+ None \d+ \d+
-#hello.obj:
-# implicit:
-# hello.c: None \S+ \d+ \d+
-# inc1.h: None \S+ \d+ \d+
-# inc2.h: None \S+ \d+ \d+
-#""")
-
-test.run_sconsign(arguments = "-e hello.obj work1/sub2/.sconsign work1/sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
-
-test.run(chdir = 'work1', arguments = '--clean .')
-
-test.write(['work1', 'SConstruct'], """
-SourceSignatures('timestamp')
-TargetSignatures('content')
-env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
-env1.Program('sub1/hello.c')
-env2 = env1.Clone(CPPPATH = ['sub2'])
-env2.Program('sub2/hello.c')
-""")
-
-time.sleep(1)
-
-test.run(chdir = 'work1', arguments = '. --max-drift=1 --debug=stacktrace')
-
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj work1/sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
-
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r work1/sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.obj: \S+
-hello.obj: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.c: \S+
-""")
-
-
-##############################################################################
-
-test.write(['work2', 'SConstruct'], """
-SConsignFile()
-env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
-env1.Program('sub1/hello.c')
-env2 = env1.Clone(CPPPATH = ['sub2'])
-env2.Program('sub2/hello.c')
-""")
-
-test.write(['work2', 'sub1', 'hello.c'], r"""\
-#include <stdio.h>
-#include <stdlib.h>
-int
-main(int argc, char *argv[])
-{
- argv[argc++] = "--";
- printf("sub1/hello.c\n");
- exit (0);
-}
-""")
-
-test.write(['work2', 'sub2', 'hello.c'], r"""\
-#include <stdio.h>
-#include <stdlib.h>
-#include <inc1.h>
-#include <inc2.h>
-int
-main(int argc, char *argv[])
-{
- argv[argc++] = "--";
- printf("sub2/goodbye.c\n");
- exit (0);
-}
-""")
-
-test.write(['work2', 'sub2', 'inc1.h'], r"""\
-#define STRING1 "inc1.h"
-""")
-
-test.write(['work2', 'sub2', 'inc2.h'], r"""\
-#define STRING2 "inc2.h"
-""")
-
-test.run(chdir = 'work2', arguments = '--implicit-cache .')
-
-test.run_sconsign(arguments = "work2/.sconsign")
-
-test.run_sconsign(arguments = "work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-=== sub2:
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
-
-test.run_sconsign(arguments = "--raw work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
-=== sub2:
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
-
-test.run_sconsign(arguments = "-v work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.exe:
- bsig: \S+
- csig: None
- timestamp: \d+
- size: \d+
- implicit:
- hello.obj: \S+
-hello.obj:
- bsig: \S+
- csig: None
- timestamp: \d+
- size: \d+
- implicit:
- hello.c: \S+
-=== sub2:
-hello.exe:
- bsig: \S+
- csig: None
- timestamp: \d+
- size: \d+
- implicit:
- hello.obj: \S+
-hello.obj:
- bsig: \S+
- csig: None
- timestamp: \d+
- size: \d+
- implicit:
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
-
-test.run_sconsign(arguments = "-b -v work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-=== sub2:
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-""")
-
-test.run_sconsign(arguments = "-c -v work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.exe:
- csig: None
-hello.obj:
- csig: None
-=== sub2:
-hello.exe:
- csig: None
-hello.obj:
- csig: None
-""")
-
-test.run_sconsign(arguments = "-s -v work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.exe:
- size: \d+
-hello.obj:
- size: \d+
-=== sub2:
-hello.exe:
- size: \d+
-hello.obj:
- size: \d+
-""")
-
-test.run_sconsign(arguments = "-t -v work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.exe:
- timestamp: \d+
-hello.obj:
- timestamp: \d+
-=== sub2:
-hello.exe:
- timestamp: \d+
-hello.obj:
- timestamp: \d+
-""")
-
-test.run_sconsign(arguments = "-e hello.obj work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-=== sub2:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
-
-test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj work2/.sconsign",
- stdout = """\
-=== sub1:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-=== sub2:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
-
-#test.run_sconsign(arguments = "-i -v work2/.sconsign",
-# stdout = """\
-#=== sub1:
-#hello.exe:
-# implicit:
-# hello.obj: \S+
-#hello.obj:
-# implicit:
-# hello.c: \S+
-#=== sub2:
-#hello.exe:
-# implicit:
-# hello.obj: \S+
-#hello.obj:
-# implicit:
-# hello.c: \S+
-# inc1.h: \S+
-# inc2.h: \S+
-#""")
-
-test.run(chdir = 'work2', arguments = '--clean .')
-
-test.write(['work2','SConstruct'], """
-SConsignFile('my_sconsign')
-SourceSignatures('timestamp')
-TargetSignatures('content')
-env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
-env1.Program('sub1/hello.c')
-env2 = env1.Clone(CPPPATH = ['sub2'])
-env2.Program('sub2/hello.c')
-""")
-
-time.sleep(1)
-
-test.run(chdir = 'work2', arguments = '. --max-drift=1')
-
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign",
- stdout = """\
-=== sub1:
-hello.exe: \d+ None \d+ \d+
- hello.obj: \d+
-hello.obj: \d+ None \d+ \d+
- hello.c: \d+
-""")
-
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign.dblite",
- stdout = """\
-=== sub1:
-hello.exe: \d+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \d+ None \d+ \d+
- hello.c: \S+
-""")
-
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign",
- stdout = """\
-=== sub1:
-hello.exe: \d+ None \d+ \d+
- hello.obj: \d+
-hello.obj: \d+ None \d+ \d+
- hello.c: \d+
-""")
-
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj -d sub1 -f dblite work2/my_sconsign.dblite",
- stdout = """\
-=== sub1:
-hello.exe: \S+ None \d+ \d+
- hello.obj: \d+
-hello.obj: \S+ None \d+ \d+
- hello.c: \d+
-""")
-
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r -d sub1 -f dblite work2/my_sconsign",
- stdout = """\
-=== sub1:
-hello.exe: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.obj: \d+
-hello.obj: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.c: \d+
-""")
-
-test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r -d sub1 -f dblite work2/my_sconsign.dblite",
- stdout = """\
-=== sub1:
-hello.exe: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.obj: \d+
-hello.obj: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.c: \d+
-""")
-
-##############################################################################
-
-test.write('bad1', "bad1\n")
-test.write('bad2.dblite', "bad2.dblite\n")
-test.write('bad3', "bad3\n")
-
-test.run_sconsign(arguments = "-f dblite no_sconsign",
- stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n")
-
-test.run_sconsign(arguments = "-f dblite bad1",
- stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n")
-
-test.run_sconsign(arguments = "-f dblite bad1.dblite",
- stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n")
-
-test.run_sconsign(arguments = "-f dblite bad2",
- stderr = "sconsign: ignoring invalid `dblite' file `bad2'\n")
-
-test.run_sconsign(arguments = "-f dblite bad2.dblite",
- stderr = "sconsign: ignoring invalid `dblite' file `bad2.dblite'\n")
-
-test.run_sconsign(arguments = "-f sconsign no_sconsign",
- stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n")
-
-test.run_sconsign(arguments = "-f sconsign bad3",
- stderr = "sconsign: ignoring invalid .sconsign file `bad3'\n")
-
-test.pass_test()
diff --git a/test/sconsign/script/SConsignFile.py b/test/sconsign/script/SConsignFile.py
new file mode 100644
index 0000000..2f5ddf3
--- /dev/null
+++ b/test/sconsign/script/SConsignFile.py
@@ -0,0 +1,260 @@
+#!/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__"
+
+"""
+Verify that the sconsign script works with files generated when
+using the signatures in an SConsignFile().
+"""
+
+import TestSConsign
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+test.subdir('sub1', 'sub2')
+
+test.write(['SConstruct'], """\
+SConsignFile()
+env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
+env1.Program('sub1/hello.c')
+env2 = env1.Clone(CPPPATH = ['sub2'])
+env2.Program('sub2/hello.c')
+""")
+
+test.write(['sub1', 'hello.c'], r"""\
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub1/hello.c\n");
+ exit (0);
+}
+""")
+
+test.write(['sub2', 'hello.c'], r"""\
+#include <stdio.h>
+#include <stdlib.h>
+#include <inc1.h>
+#include <inc2.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub2/goodbye.c\n");
+ exit (0);
+}
+""")
+
+test.write(['sub2', 'inc1.h'], r"""\
+#define STRING1 "inc1.h"
+""")
+
+test.write(['sub2', 'inc2.h'], r"""\
+#define STRING2 "inc2.h"
+""")
+
+test.run(arguments = '--implicit-cache .')
+
+test.run_sconsign(arguments = ".sconsign",
+ stdout = """\
+=== sub1:
+hello.exe: \S+ None \d+ \d+
+ hello.obj: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+=== sub2:
+hello.exe: \S+ None \d+ \d+
+ hello.obj: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+ inc1.h: \S+
+ inc2.h: \S+
+""")
+
+test.run_sconsign(arguments = "--raw .sconsign",
+ stdout = """\
+=== sub1:
+hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
+ hello.obj: \S+
+hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
+ hello.c: \S+
+=== sub2:
+hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
+ hello.obj: \S+
+hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
+ hello.c: \S+
+ inc1.h: \S+
+ inc2.h: \S+
+""")
+
+test.run_sconsign(arguments = "-v .sconsign",
+ stdout = """\
+=== sub1:
+hello.exe:
+ bsig: \S+
+ csig: None
+ timestamp: \d+
+ size: \d+
+ implicit:
+ hello.obj: \S+
+hello.obj:
+ bsig: \S+
+ csig: None
+ timestamp: \d+
+ size: \d+
+ implicit:
+ hello.c: \S+
+=== sub2:
+hello.exe:
+ bsig: \S+
+ csig: None
+ timestamp: \d+
+ size: \d+
+ implicit:
+ hello.obj: \S+
+hello.obj:
+ bsig: \S+
+ csig: None
+ timestamp: \d+
+ size: \d+
+ implicit:
+ hello.c: \S+
+ inc1.h: \S+
+ inc2.h: \S+
+""")
+
+test.run_sconsign(arguments = "-b -v .sconsign",
+ stdout = """\
+=== sub1:
+hello.exe:
+ bsig: \S+
+hello.obj:
+ bsig: \S+
+=== sub2:
+hello.exe:
+ bsig: \S+
+hello.obj:
+ bsig: \S+
+""")
+
+test.run_sconsign(arguments = "-c -v .sconsign",
+ stdout = """\
+=== sub1:
+hello.exe:
+ csig: None
+hello.obj:
+ csig: None
+=== sub2:
+hello.exe:
+ csig: None
+hello.obj:
+ csig: None
+""")
+
+test.run_sconsign(arguments = "-s -v .sconsign",
+ stdout = """\
+=== sub1:
+hello.exe:
+ size: \d+
+hello.obj:
+ size: \d+
+=== sub2:
+hello.exe:
+ size: \d+
+hello.obj:
+ size: \d+
+""")
+
+test.run_sconsign(arguments = "-t -v .sconsign",
+ stdout = """\
+=== sub1:
+hello.exe:
+ timestamp: \d+
+hello.obj:
+ timestamp: \d+
+=== sub2:
+hello.exe:
+ timestamp: \d+
+hello.obj:
+ timestamp: \d+
+""")
+
+test.run_sconsign(arguments = "-e hello.obj .sconsign",
+ stdout = """\
+=== sub1:
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+=== sub2:
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+ inc1.h: \S+
+ inc2.h: \S+
+""")
+
+test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj .sconsign",
+ stdout = """\
+=== sub1:
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+hello.exe: \S+ None \d+ \d+
+ hello.obj: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+=== sub2:
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+ inc1.h: \S+
+ inc2.h: \S+
+hello.exe: \S+ None \d+ \d+
+ hello.obj: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+ inc1.h: \S+
+ inc2.h: \S+
+""")
+
+#test.run_sconsign(arguments = "-i -v .sconsign",
+# stdout = """\
+#=== sub1:
+#hello.exe:
+# implicit:
+# hello.obj: \S+
+#hello.obj:
+# implicit:
+# hello.c: \S+
+#=== sub2:
+#hello.exe:
+# implicit:
+# hello.obj: \S+
+#hello.obj:
+# implicit:
+# hello.c: \S+
+# inc1.h: \S+
+# inc2.h: \S+
+#""")
+
+test.pass_test()
diff --git a/test/sconsign/script/Signatures.py b/test/sconsign/script/Signatures.py
new file mode 100644
index 0000000..9a3ce62
--- /dev/null
+++ b/test/sconsign/script/Signatures.py
@@ -0,0 +1,109 @@
+#!/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__"
+
+"""
+Verify that the sconsign script works when using a .sconsign file in
+each subdirectory (SConsignFile(None)) written with the non-default
+SourceSignatures() and TargetSignatures() values (timestamp and content,
+respectively).
+"""
+
+import TestSConsign
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+def re_sep(*args):
+ import os.path
+ import re
+ return re.escape(apply(os.path.join, args))
+
+test.subdir('sub1', 'sub2')
+
+test.write('SConstruct', """
+SConsignFile(None)
+SourceSignatures('timestamp')
+TargetSignatures('content')
+env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
+env1.Program('sub1/hello.c')
+env2 = env1.Clone(CPPPATH = ['sub2'])
+env2.Program('sub2/hello.c')
+""")
+
+test.write(['sub1', 'hello.c'], r"""\
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub1/hello.c\n");
+ exit (0);
+}
+""")
+
+test.write(['sub2', 'hello.c'], r"""\
+#include <stdio.h>
+#include <stdlib.h>
+#include <inc1.h>
+#include <inc2.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub2/goodbye.c\n");
+ exit (0);
+}
+""")
+
+test.write(['sub2', 'inc1.h'], r"""\
+#define STRING1 "inc1.h"
+""")
+
+test.write(['sub2', 'inc2.h'], r"""\
+#define STRING2 "inc2.h"
+""")
+
+test.sleep()
+
+test.run(arguments = '. --max-drift=1')
+
+test.run_sconsign(arguments = "-e hello.exe -e hello.obj sub1/.sconsign",
+ stdout = """\
+hello.exe: \S+ None \d+ \d+
+ hello.obj: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+""")
+
+test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r sub1/.sconsign",
+ stdout = """\
+hello.exe: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
+ hello.obj: \S+
+hello.obj: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
+ hello.c: \S+
+""")
+
+test.pass_test()
diff --git a/test/sconsign/script/bad.py b/test/sconsign/script/bad.py
new file mode 100644
index 0000000..3ada44c
--- /dev/null
+++ b/test/sconsign/script/bad.py
@@ -0,0 +1,61 @@
+#!/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__"
+
+"""
+Verify that the sconsign script generates appropriate error messages when
+passed various non-existent or bad sconsign files as arguments.
+"""
+
+import TestSConsign
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+test.write('bad1', "bad1\n")
+test.write('bad2.dblite', "bad2.dblite\n")
+test.write('bad3', "bad3\n")
+
+test.run_sconsign(arguments = "-f dblite no_sconsign",
+ stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n")
+
+test.run_sconsign(arguments = "-f dblite bad1",
+ stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n")
+
+test.run_sconsign(arguments = "-f dblite bad1.dblite",
+ stderr = "sconsign: \[Errno 2\] No such file or directory: 'bad1.dblite'\n")
+
+test.run_sconsign(arguments = "-f dblite bad2",
+ stderr = "sconsign: ignoring invalid `dblite' file `bad2'\n")
+
+test.run_sconsign(arguments = "-f dblite bad2.dblite",
+ stderr = "sconsign: ignoring invalid `dblite' file `bad2.dblite'\n")
+
+test.run_sconsign(arguments = "-f sconsign no_sconsign",
+ stderr = "sconsign: \[Errno 2\] No such file or directory: 'no_sconsign'\n")
+
+test.run_sconsign(arguments = "-f sconsign bad3",
+ stderr = "sconsign: ignoring invalid .sconsign file `bad3'\n")
+
+test.pass_test()
diff --git a/test/sconsign/script/dblite.py b/test/sconsign/script/dblite.py
new file mode 100644
index 0000000..fe49df6
--- /dev/null
+++ b/test/sconsign/script/dblite.py
@@ -0,0 +1,122 @@
+#!/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__"
+
+"""
+Verify that various ways of getting at a an sconsign file written with
+the default dblite module and default .dblite suffix work correctly.
+"""
+
+import TestSConsign
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+test.subdir('sub1', 'sub2')
+
+test.write('SConstruct', """
+SConsignFile('my_sconsign')
+SourceSignatures('timestamp')
+TargetSignatures('content')
+env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
+env1.Program('sub1/hello.c')
+env2 = env1.Clone(CPPPATH = ['sub2'])
+env2.Program('sub2/hello.c')
+""")
+
+test.write(['sub1', 'hello.c'], r"""\
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub1/hello.c\n");
+ exit (0);
+}
+""")
+
+test.write(['sub2', 'hello.c'], r"""\
+#include <stdio.h>
+#include <stdlib.h>
+#include <inc1.h>
+#include <inc2.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub2/goodbye.c\n");
+ exit (0);
+}
+""")
+
+test.write(['sub2', 'inc1.h'], r"""\
+#define STRING1 "inc1.h"
+""")
+
+test.write(['sub2', 'inc2.h'], r"""\
+#define STRING2 "inc2.h"
+""")
+
+test.sleep()
+
+test.run(arguments = '. --max-drift=1')
+
+expect = """\
+=== sub1:
+hello.exe: \d+ None \d+ \d+
+ hello.obj: \d+
+hello.obj: \d+ None \d+ \d+
+ hello.c: \d+
+"""
+
+expect_r = """\
+=== sub1:
+hello.exe: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
+ hello.obj: \d+
+hello.obj: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
+ hello.c: \d+
+"""
+
+common_flags = '-e hello.exe -e hello.obj -d sub1'
+
+test.run_sconsign(arguments = "%s my_sconsign" % common_flags,
+ stdout = expect)
+
+test.run_sconsign(arguments = "%s my_sconsign.dblite" % common_flags,
+ stdout = expect)
+
+test.run_sconsign(arguments = "%s -f dblite my_sconsign" % common_flags,
+ stdout = expect)
+
+test.run_sconsign(arguments = "%s -f dblite my_sconsign.dblite" % common_flags,
+ stdout = expect)
+
+test.run_sconsign(arguments = "%s -r -f dblite my_sconsign" % common_flags,
+ stdout = expect_r)
+
+test.run_sconsign(arguments = "%s -r -f dblite my_sconsign.dblite" % common_flags,
+ stdout = expect_r)
+
+test.pass_test()
diff --git a/test/sconsign/script/no-SConsignFile.py b/test/sconsign/script/no-SConsignFile.py
new file mode 100644
index 0000000..b860770
--- /dev/null
+++ b/test/sconsign/script/no-SConsignFile.py
@@ -0,0 +1,205 @@
+#!/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__"
+
+"""
+Verify that the sconsign script works when using an individual
+.sconsign file in each directory (SConsignFile(None)).
+"""
+
+import TestSConsign
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+def re_sep(*args):
+ import os.path
+ import re
+ return re.escape(apply(os.path.join, args))
+
+test.subdir('sub1', 'sub2')
+
+test.write(['SConstruct'], """
+SConsignFile(None)
+env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
+env1.Program('sub1/hello.c')
+env2 = env1.Clone(CPPPATH = ['sub2'])
+env2.Program('sub2/hello.c')
+""")
+
+test.write(['sub1', 'hello.c'], r"""\
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub1/hello.c\n");
+ exit (0);
+}
+""")
+
+test.write(['sub2', 'hello.c'], r"""\
+#include <stdio.h>
+#include <stdlib.h>
+#include <inc1.h>
+#include <inc2.h>
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("sub2/goodbye.c\n");
+ exit (0);
+}
+""")
+
+test.write(['sub2', 'inc1.h'], r"""\
+#define STRING1 "inc1.h"
+""")
+
+test.write(['sub2', 'inc2.h'], r"""\
+#define STRING2 "inc2.h"
+""")
+
+test.run(arguments = '--implicit-cache .')
+
+test.run_sconsign(arguments = "sub1/.sconsign",
+ stdout = """\
+hello.exe: \S+ None \d+ \d+
+ hello.obj: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+""")
+
+test.run_sconsign(arguments = "--raw sub1/.sconsign",
+ stdout = """\
+hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
+ hello.obj: \S+
+hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
+ hello.c: \S+
+""")
+
+test.run_sconsign(arguments = "-v sub1/.sconsign",
+ stdout = """\
+hello.exe:
+ bsig: \S+
+ csig: None
+ timestamp: \d+
+ size: \d+
+ implicit:
+ hello.obj: \S+
+hello.obj:
+ bsig: \S+
+ csig: None
+ timestamp: \d+
+ size: \d+
+ implicit:
+ hello.c: \S+
+""")
+
+test.run_sconsign(arguments = "-b -v sub1/.sconsign",
+ stdout = """\
+hello.exe:
+ bsig: \S+
+hello.obj:
+ bsig: \S+
+""")
+
+test.run_sconsign(arguments = "-c -v sub1/.sconsign",
+ stdout = """\
+hello.exe:
+ csig: None
+hello.obj:
+ csig: None
+""")
+
+test.run_sconsign(arguments = "-s -v sub1/.sconsign",
+ stdout = """\
+hello.exe:
+ size: \d+
+hello.obj:
+ size: \d+
+""")
+
+test.run_sconsign(arguments = "-t -v sub1/.sconsign",
+ stdout = """\
+hello.exe:
+ timestamp: \d+
+hello.obj:
+ timestamp: \d+
+""")
+
+test.run_sconsign(arguments = "-e hello.obj sub1/.sconsign",
+ stdout = """\
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+""")
+
+test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj sub1/.sconsign",
+ stdout = """\
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+hello.exe: \S+ None \d+ \d+
+ hello.obj: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+""")
+
+# XXX NOT SURE IF THIS IS RIGHT!
+sub2_inc1_h = re_sep('sub2', 'inc1.h')
+sub2_inc2_h = re_sep('sub2', 'inc2.h')
+
+test.run_sconsign(arguments = "sub2/.sconsign",
+ stdout = """\
+hello.exe: \S+ None \d+ \d+
+ hello.obj: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+ inc1.h: \S+
+ inc2.h: \S+
+""")
+
+#test.run_sconsign(arguments = "-i -v sub2/.sconsign",
+# stdout = """\
+#hello.exe:
+# implicit:
+# hello.obj: \S+ None \d+ \d+
+#hello.obj:
+# implicit:
+# hello.c: None \S+ \d+ \d+
+# inc1.h: None \S+ \d+ \d+
+# inc2.h: None \S+ \d+ \d+
+#""")
+
+test.run_sconsign(arguments = "-e hello.obj sub2/.sconsign sub1/.sconsign",
+ stdout = """\
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+ inc1.h: \S+
+ inc2.h: \S+
+hello.obj: \S+ None \d+ \d+
+ hello.c: \S+
+""")
+
+test.pass_test()
diff --git a/test/symlink/BuildDir.py b/test/symlink/BuildDir.py
index eee0e4d..6394e0a 100644
--- a/test/symlink/BuildDir.py
+++ b/test/symlink/BuildDir.py
@@ -50,10 +50,14 @@ Program('hello', ['obj/subdir/main.c'])
""")
test.write(['srcdir', 'main.c'], r"""
+#include <stdio.h>
+#include <stdlib.h>
+
int
main(int ac, char *argv[])
{
printf("srcdir/main.c\n");
+ exit(0);
}
""")