summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2008-02-04 19:07:24 (GMT)
committerSteven Knight <knight@baldmt.com>2008-02-04 19:07:24 (GMT)
commitbe25024e65a30e65a9e3799ffa5323e23f49003d (patch)
tree439714b7733dd4ffe858b1fc15e15fa3e036048d /test
parent0abfc01296f0184fb6c997400b92cfa7e48d81ef (diff)
downloadSCons-be25024e65a30e65a9e3799ffa5323e23f49003d.zip
SCons-be25024e65a30e65a9e3799ffa5323e23f49003d.tar.gz
SCons-be25024e65a30e65a9e3799ffa5323e23f49003d.tar.bz2
Merged revisions 2527-2645 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core ........ r2528 | stevenknight | 2007-12-13 06:08:21 -0800 (Thu, 13 Dec 2007) | 5 lines Remove the .del_binfo() method, no longer needed since the Big Signature Refactoring causes us to visit every Node in order during the DAG walk, and the BuildInfo object now just holds information for storage in the .sconsign file. ........ r2529 | stevenknight | 2007-12-13 13:17:15 -0800 (Thu, 13 Dec 2007) | 3 lines Fix the --keep-going flag so it builds all possible targets even when a later top-level target depends on a child that failed its build. ........ r2530 | stevenknight | 2007-12-14 04:02:05 -0800 (Fri, 14 Dec 2007) | 4 lines Issue 1715: BuildDir(duplicate=0) support for Tex/LaTeX. Re-run LaTeX in response to package warnings. (Rob Managan) ........ r2531 | stevenknight | 2007-12-14 07:14:31 -0800 (Fri, 14 Dec 2007) | 3 lines Refactor the max_drift logic around fetching stored signatures into its own new method. ........ r2532 | stevenknight | 2007-12-14 07:18:44 -0800 (Fri, 14 Dec 2007) | 3 lines Have get_csig() return the stored content signature if max_drift says it's okay. ........ r2533 | stevenknight | 2007-12-14 18:34:51 -0800 (Fri, 14 Dec 2007) | 2 lines Issue 1859: Support SWIG statements like %module(directors="1"). ........ r2534 | stevenknight | 2007-12-15 03:51:13 -0800 (Sat, 15 Dec 2007) | 3 lines Python 2.1 portability fix w.r.t. "import SCons" and "import SCons.platform.win32" and binding local variables and whatnot. ........ r2535 | stevenknight | 2007-12-15 03:51:56 -0800 (Sat, 15 Dec 2007) | 2 lines Python 1.5 fix: use the -classic flag when invoking SWIG. ........ r2536 | stevenknight | 2007-12-15 06:03:48 -0800 (Sat, 15 Dec 2007) | 4 lines Support subclasses of the new-style str() class as input to Builders and the like. Also speed up all of the Util.is_*() functions when using new-style classes by just using isinstance() internally. ........ r2537 | stevenknight | 2007-12-15 06:35:49 -0800 (Sat, 15 Dec 2007) | 3 lines Issue 1851: Fix being able to use $PDB and $WINDOWS_INSERT_MANIFEST together. (Benoit Belley) ........ r2538 | stevenknight | 2007-12-15 06:59:43 -0800 (Sat, 15 Dec 2007) | 3 lines Handle dangling entries for the Intel C compiler in the Windows registry. (Benoit Belley) ........ r2539 | stevenknight | 2007-12-15 09:51:59 -0800 (Sat, 15 Dec 2007) | 2 lines Reorganize library-related tests into a separate subdirectory. ........ r2540 | stevenknight | 2007-12-15 09:57:29 -0800 (Sat, 15 Dec 2007) | 4 lines Issue 1850: better support for non-standard shared library prefixes and suffixes by stripping all prefixes and suffixes in lists of $SHLIBPREFIXES and $SHLIBSUFFIXES. (Benoit Belley) ........ r2541 | stevenknight | 2007-12-15 18:49:15 -0800 (Sat, 15 Dec 2007) | 2 lines Python 1.5 portability fixes. ........ r2542 | stevenknight | 2007-12-15 19:02:39 -0800 (Sat, 15 Dec 2007) | 3 lines Issue 1768: Have the D language scanner search for .di files as well as .d files. (Jerome Berger) ........ r2543 | stevenknight | 2007-12-16 14:31:40 -0800 (Sun, 16 Dec 2007) | 3 lines Add a find_include_names() method to the Scanner.Classic class to abstract out how included names can be generated by subclasses. (Jerome Berger) ........ r2544 | stevenknight | 2007-12-16 14:31:54 -0800 (Sun, 16 Dec 2007) | 3 lines Add a find_include_names() method to the Scanner.Classic class to abstract out how included names can be generated by subclasses. (Jerome Berger) ........ r2545 | stevenknight | 2007-12-16 15:04:43 -0800 (Sun, 16 Dec 2007) | 3 lines Issue 1860: Support the D scanner returning multiple modules from a single import statement. (Jerome Berger) ........ r2546 | stevenknight | 2007-12-16 17:41:17 -0800 (Sun, 16 Dec 2007) | 3 lines Issue 1861: Fix the ability to #include a file (or search other $*PATH variables) that has an absoluate path. ........ r2547 | stevenknight | 2007-12-18 08:09:59 -0800 (Tue, 18 Dec 2007) | 2 lines Replace uses of "is_List() or is_Tuple()" with is_Sequence(). ........ r2548 | stevenknight | 2007-12-18 08:13:14 -0800 (Tue, 18 Dec 2007) | 2 lines Report the incorrect value in assertions. ........ r2549 | stevenknight | 2007-12-19 07:58:56 -0800 (Wed, 19 Dec 2007) | 3 lines Fix handling #includes of absolute path names when the path doesn't exist (implicitly, because it's #ifdef'ed out). ........ r2550 | stevenknight | 2007-12-19 08:29:24 -0800 (Wed, 19 Dec 2007) | 4 lines Fix test path examination when the temporary directory location is redirected via symlinks (e.g. /usr/tmp -> /var/tmp on Red Hat). (Benoit Belley) ........ r2551 | stevenknight | 2007-12-19 08:30:17 -0800 (Wed, 19 Dec 2007) | 2 lines Fix scons-time path reporting when symlinks are involved. (Benoit Belley) ........ r2552 | stevenknight | 2007-12-19 22:51:18 -0800 (Wed, 19 Dec 2007) | 4 lines Issue 1855: Reduce the worker thread stack size to a default of 256 Kbytes. Add a --stack-size= command-line option, also configurable via SetOption('stack_size'). (Benoit Belley) ........ r2553 | stevenknight | 2007-12-20 18:25:50 -0800 (Thu, 20 Dec 2007) | 2 lines Skip this test if SWIG isn't installed. ........ r2554 | stevenknight | 2007-12-20 18:26:21 -0800 (Thu, 20 Dec 2007) | 2 lines Accomodate slightly different permissions errors on Ubuntu Gutsy. ........ r2555 | stevenknight | 2007-12-21 02:12:09 -0800 (Fri, 21 Dec 2007) | 3 lines Fix a Python 2.2 quirk in the reported file name ("<string>") when encountering a SyntaxError in a SConstruct file. ........ r2556 | stevenknight | 2007-12-21 02:12:35 -0800 (Fri, 21 Dec 2007) | 2 lines Enforce order between the build of f1.out and f2.out. ........ r2557 | stevenknight | 2007-12-21 02:12:55 -0800 (Fri, 21 Dec 2007) | 2 lines Don't die if the Python version doesn't have os.path.realpath(). ........ r2558 | stevenknight | 2007-12-21 02:13:19 -0800 (Fri, 21 Dec 2007) | 2 lines Refactor the test/build-errors.py script into separate scripts for each test. ........ r2559 | stevenknight | 2007-12-21 08:08:12 -0800 (Fri, 21 Dec 2007) | 3 lines Issue 1864: Add a CheckDeclaration() call to configure contexts. (David Cournapeau) ........ r2560 | stevenknight | 2007-12-21 08:18:47 -0800 (Fri, 21 Dec 2007) | 2 lines Issue 1865: Improve the CheckTypeSize() code. (David Cournapeau) ........ r2561 | stevenknight | 2007-12-21 08:21:47 -0800 (Fri, 21 Dec 2007) | 2 lines Fix os.path.realpath() handling (a Python 2.1 portability issue). ........ r2562 | stevenknight | 2007-12-21 14:08:39 -0800 (Fri, 21 Dec 2007) | 2 lines Split CPPDEFINES.py into separate sub-test scripts. ........ r2563 | stevenknight | 2007-12-21 15:56:26 -0800 (Fri, 21 Dec 2007) | 6 lines Support proper expansion of construction variables containing lists within expansions like $CPPPATH. Change env.subst() to return a list, not a joined string, when the input is a list. (Konstantin Bozhikov) ........ r2564 | stevenknight | 2007-12-22 04:15:11 -0800 (Sat, 22 Dec 2007) | 2 lines Normalize the ModDate field when comparing generated PDF files. ........ r2565 | stevenknight | 2007-12-22 22:01:45 -0800 (Sat, 22 Dec 2007) | 5 lines Java test refactoring to commonize construction environment initialization and searching for javac / javah / jar / rmic. Don't look for *_Skel.class files to be created by Java 1.[56]. Minor Java code changes to deal with compiler warnings. ........ r2566 | stevenknight | 2007-12-23 05:20:45 -0800 (Sun, 23 Dec 2007) | 2 lines Don't still look for *_Skel.class files. ........ r2567 | stevenknight | 2007-12-23 07:30:36 -0800 (Sun, 23 Dec 2007) | 5 lines Fix Intel C compiler issues: Issue 1863: Fix failure to match /opt/intel_cc_* directories. (Benoit Belley) Issue 1866: Fix topdir when the version isn't specified. (Jonas Olsson) Issue 1867: Fix use of network licenses. (Jonas Olsson) ........ r2573 | stevenknight | 2008-01-01 09:59:16 -0800 (Tue, 01 Jan 2008) | 3 lines Add asynchronous subprocess communication via new start() and finish() methods. ........ r2574 | stevenknight | 2008-01-01 10:02:26 -0800 (Tue, 01 Jan 2008) | 4 lines Minor code cleanup: attach the version string to the options parser object, instead of passing it in to deal with the lack of nested scopes in Python 1.5.2. ........ r2575 | stevenknight | 2008-01-01 10:08:46 -0800 (Tue, 01 Jan 2008) | 4 lines Rename the CacheDir class and let the name CacheDir be a variable that can be reset at will, depending on whether CacheDir() support is enabled or disabled at any particular time. ........ r2576 | stevenknight | 2008-01-01 10:14:58 -0800 (Tue, 01 Jan 2008) | 2 lines Restore the Node.del_binfo() method and its call in Node.clear(). ........ r2577 | stevenknight | 2008-01-02 07:51:25 -0800 (Wed, 02 Jan 2008) | 6 lines Refactor CacheDir support (again) for --interactive mode. Delay effects of --cache-* settings until they're needed by getting rid of the Null() object pattern and the functional programming idiom of replacing the CacheDebug method. Have the Environment.CacheDir() method just record the path for later instantiation. ........ r2578 | stevenknight | 2008-01-02 18:48:12 -0800 (Wed, 02 Jan 2008) | 3 lines Issue 1657: Add a --interactive option to create a command-line interpreter for re-building targets without re-reading SConscript files. ........ r2579 | stevenknight | 2008-01-02 21:54:38 -0800 (Wed, 02 Jan 2008) | 2 lines Python 1.5.2 portability fix (no use of +=). ........ r2580 | stevenknight | 2008-01-02 21:54:47 -0800 (Wed, 02 Jan 2008) | 3 lines Use a regular expression to avoid having to match a specific MD5 checksum value in the --cache-debug output. ........ r2581 | stevenknight | 2008-01-02 21:54:59 -0800 (Wed, 02 Jan 2008) | 4 lines Don't bother looking for shlex.split(), since our compatibility layer provides it in older Python version. Make the compatibility version of shlex.split() not treat '.' as a token separator. ........ r2582 | stevenknight | 2008-01-02 21:56:15 -0800 (Wed, 02 Jan 2008) | 3 lines Python 1.5.2 portability fixes: no list comprehensions, no nested scopes, no "for x in" a dictionary. ........ r2583 | stevenknight | 2008-01-03 07:39:59 -0800 (Thu, 03 Jan 2008) | 3 lines Fix a left-over use of a string method. Fix printing --interactive help text, which I outright broke last checkin. ........ r2584 | stevenknight | 2008-01-03 07:58:56 -0800 (Thu, 03 Jan 2008) | 4 lines Import the vanilla Python2.5 shlex module, which we'll use as a basis for retrofitting to old Python versions to provide shlex.split() functionality. ........ r2585 | stevenknight | 2008-01-03 08:01:02 -0800 (Thu, 03 Jan 2008) | 3 lines Modifications to the vanilla Python 2.5 shlex module to make it work back to Python 1.5. ........ r2586 | stevenknight | 2008-01-03 08:04:31 -0800 (Thu, 03 Jan 2008) | 3 lines Use the new shlex compatibility module if we're using an old version of Python with a native shlex module that has no shlex.split() function. ........ r2587 | stevenknight | 2008-01-03 09:31:15 -0800 (Thu, 03 Jan 2008) | 3 lines Fix the ParseFlags() unit test now that we have a real shlex.split() function even on earlier Python versions. ........ r2588 | stevenknight | 2008-01-06 04:52:05 -0800 (Sun, 06 Jan 2008) | 3 lines Add compat/_scons_shlex.py to exception lists for __copyright__ and __revision__ strings. ........ r2589 | stevenknight | 2008-01-06 06:32:07 -0800 (Sun, 06 Jan 2008) | 2 lines Remove leftover debug print. ........ r2590 | stevenknight | 2008-01-06 07:35:46 -0800 (Sun, 06 Jan 2008) | 3 lines Change the test to work by wrapping the public .__call__() method of the C scanner, instead of the internal .scan() method. ........ r2591 | stevenknight | 2008-01-06 07:39:12 -0800 (Sun, 06 Jan 2008) | 3 lines Use the public CScan.path() method, not the internal CScan.path_function attribute. ........ r2592 | stevenknight | 2008-01-07 02:55:53 -0800 (Mon, 07 Jan 2008) | 2 lines Use a tuple instead of a list for the cpp module path(s). ........ r2593 | stevenknight | 2008-01-07 03:10:28 -0800 (Mon, 07 Jan 2008) | 2 lines Don't die if a macro function expands to a non-string (an integer). ........ r2594 | stevenknight | 2008-01-07 03:29:12 -0800 (Mon, 07 Jan 2008) | 3 lines Python 1.5 throws TypeError, not AttributeError if you try to string.split() a non-string value. ........ r2595 | stevenknight | 2008-01-07 03:30:18 -0800 (Mon, 07 Jan 2008) | 3 lines Reduce duplicate execution of individual test_*() unit test methods by eliminating duplicates (if the set() type is avaiable). ........ r2596 | stevenknight | 2008-01-07 06:57:30 -0800 (Mon, 07 Jan 2008) | 6 lines Add a basic test of in-line #include handling. Sort the test names. Don't os.path.join() the directory name if we find the file in the current directory. Use os.curdir instead of hard-coding '.' as the current directory. ........ r2597 | stevenknight | 2008-01-07 06:59:29 -0800 (Mon, 07 Jan 2008) | 3 lines Read files with a new .read_file() method, so it can be overridden by subclasses. ........ r2598 | stevenknight | 2008-01-07 17:59:50 -0800 (Mon, 07 Jan 2008) | 6 lines Record the name of the file currently being processed. Make the public API (the .__call__() method) passing in a file name to be opened, and have it call a new, separate .process_contents() method (the old .__call__() method) for handling in-memory strings. ........ r2599 | stevenknight | 2008-01-07 20:03:18 -0800 (Mon, 07 Jan 2008) | 3 lines Make the test failure informative when we don't find the includes we expect by printing the expected string and actual output. ........ r2600 | stevenknight | 2008-01-07 20:24:21 -0800 (Mon, 07 Jan 2008) | 2 lines Handle no white space after #include (e.g. #include<foo.h>). ........ r2601 | stevenknight | 2008-01-07 21:01:27 -0800 (Mon, 07 Jan 2008) | 4 lines Fixes for older Python versions: No tempfile.mktemp(prefix=) argument. No string methods. ........ r2602 | stevenknight | 2008-01-08 20:57:30 -0800 (Tue, 08 Jan 2008) | 3 lines Fix command-line editing of --interactive mode with the readline module by only changing sys.stdout to our Unbuffered class if it isn't a tty. ........ r2603 | stevenknight | 2008-01-08 22:12:20 -0800 (Tue, 08 Jan 2008) | 4 lines Fix the --interactive "build" command with no targets: build the specified Default() targets; issue an error message but don't exit if Default(None) is explicity specified. ........ r2604 | stevenknight | 2008-01-09 05:00:36 -0800 (Wed, 09 Jan 2008) | 9 lines Improve Python functions used as actions by incorporating into their build signatures: - literal values referenced by the byte code. - values of default arguments - code of nested functions - values of variables captured by closures - names of referenced global variables and functions (Benoit Belley) ........ r2605 | stevenknight | 2008-01-09 06:39:03 -0800 (Wed, 09 Jan 2008) | 4 lines Add a Configure.Define() method for adding arbitrary #define lines to generated configure header files. (David Cournapeau) ........ r2606 | stevenknight | 2008-01-09 07:33:21 -0800 (Wed, 09 Jan 2008) | 4 lines Issue 1858: Fix the closing message when --clean and --keep-going are both used so it only reports errors if some actually occurred. (Benoit Belley) ........ r2607 | stevenknight | 2008-01-09 07:51:55 -0800 (Wed, 09 Jan 2008) | 3 lines Issue 1843: Add a gfortran Tool module for the GNU F95/F2003 compiler. (David Cournapeau) ........ r2608 | stevenknight | 2008-01-09 09:31:15 -0800 (Wed, 09 Jan 2008) | 4 lines Issue 1733: If $JARCHDIR isn't set explicitly, use the .java_classdir attribute that was set when the Java() Builder built the .class files. (Jan Nijtmans) ........ r2609 | stevenknight | 2008-01-09 11:27:28 -0800 (Wed, 09 Jan 2008) | 4 lines Allow Scanner.FindPathDirs objects to not take a dir= keyword argument when called. (The code already detects that and uses the current directory if necessary.) ........ r2610 | stevenknight | 2008-01-09 12:23:26 -0800 (Wed, 09 Jan 2008) | 3 lines Allow subclass overrides of results-handling by the addition of new initialize_result() and finalize_result() methods. ........ r2611 | stevenknight | 2008-01-09 14:49:50 -0800 (Wed, 09 Jan 2008) | 6 lines Capture new C Scanner glue code that knows how to use $CPPDEFINES to evaluate CPP #if/#ifdef/#elif/#else lines. Currently disabled (including the test script that validates the behavior) while we look for the right way to let users configure the feature, and work on performance issues with its O(N*M) algorithm. ........ r2612 | stevenknight | 2008-01-24 20:42:57 -0800 (Thu, 24 Jan 2008) | 3 lines Fix regular expression comparisons on Windows by escaping the \ path separators. ........ r2613 | stevenknight | 2008-01-24 20:49:04 -0800 (Thu, 24 Jan 2008) | 3 lines Rename a created stub script from "cmd.py" so it doesn't mistakenly get imported by the "import cmd" statement in Script/Interactive.py. ........ r2614 | stevenknight | 2008-01-24 20:56:05 -0800 (Thu, 24 Jan 2008) | 4 lines Fix a race condition between the actions executed by the worker threads by having the dependent action print its own execution line, and telling SCons to treat it silently (strfunction=None). ........ r2615 | stevenknight | 2008-01-24 20:59:03 -0800 (Thu, 24 Jan 2008) | 2 lines Remove left-over commented-out lines. ........ r2616 | stevenknight | 2008-01-24 21:59:49 -0800 (Thu, 24 Jan 2008) | 7 lines Windows portability in --interactive mode and its tests: Quote target names that may have spaces in them. Use the .exe suffix on a generated executable. Use the subprocess .wait() method to get the subprocess exit status when shelling out on Windows. Use an Unbuffered object for stderr (when it's not a tty). ........ r2617 | stevenknight | 2008-01-24 22:14:49 -0800 (Thu, 24 Jan 2008) | 3 lines Issue 1886: Fix the ability to build Aliases in --interactive mode. (Gary Oberbrunner) ........ r2618 | stevenknight | 2008-01-24 22:33:29 -0800 (Thu, 24 Jan 2008) | 3 lines Issue 1886: Handle Python versions that throw TypeError when they can't pickle a nested function. (Gary Oberbrunner) ........ r2619 | stevenknight | 2008-01-24 22:38:44 -0800 (Thu, 24 Jan 2008) | 3 lines Fix the LoadableModule.py test when run on Intel Macs (look for the string i386 in the file output, in addition to ppc). ........ r2620 | stevenknight | 2008-01-25 06:50:43 -0800 (Fri, 25 Jan 2008) | 4 lines Issue 1892: use "link" instead of "gnulink" for the Mac tool chain, since it doesn't understand the -rpath option and can't use $RPATH. (David Cournapeau) ........ r2621 | stevenknight | 2008-01-25 07:51:56 -0800 (Fri, 25 Jan 2008) | 2 lines Issue 1893: add Intel C compiler support on Mac OS X. (Benoit Belley) ........ r2622 | stevenknight | 2008-01-25 21:48:16 -0800 (Fri, 25 Jan 2008) | 2 lines Fix how we handle falling back to timestamps when no md5.py module exists. ........ r2623 | stevenknight | 2008-01-26 16:55:56 -0800 (Sat, 26 Jan 2008) | 5 lines Work around a metaclass / new.instancemethod() bug in base Python 2.2 by disallowing --debug=memoizer functionality if Python can't handle the Memoizer initialization (much like we do for earlier Python versions that don't have metaclasses at all). ........ r2624 | stevenknight | 2008-01-26 18:22:14 -0800 (Sat, 26 Jan 2008) | 4 lines Fix CacheDir by simplifying how the NullEnvironment hands back something that looks enough like a CacheDir object that the rest of the code doesn't require special handling. ........ r2625 | stevenknight | 2008-01-26 20:56:17 -0800 (Sat, 26 Jan 2008) | 2 lines Have the "scons-time time" subcommand handle empty files gracefully. ........ r2626 | stevenknight | 2008-01-26 20:57:21 -0800 (Sat, 26 Jan 2008) | 3 lines Add a Trace() statement to the Node.changed() method if the dependency lists are different lengths. ........ r2627 | stevenknight | 2008-01-26 21:30:59 -0800 (Sat, 26 Jan 2008) | 3 lines Have the "scons-time time --which" subcommand handle files that don't contain the requested results ........ r2628 | stevenknight | 2008-01-26 21:52:51 -0800 (Sat, 26 Jan 2008) | 2 lines Fix the ability to draw vertical bars with --fmt gnuplot option. ........ r2629 | stevenknight | 2008-01-26 22:23:10 -0800 (Sat, 26 Jan 2008) | 3 lines Allow "scons-time run" to copy non-archive files for timing. Document the archive_list config file variable. ........ r2630 | stevenknight | 2008-01-27 10:38:11 -0800 (Sun, 27 Jan 2008) | 3 lines Use the maximum Y value, not the maximum X value, as the top Y endpoint of a vertical bar drawn with --fmt=gnuplot. ........ r2631 | stevenknight | 2008-01-27 12:05:40 -0800 (Sun, 27 Jan 2008) | 2 lines Make scons-time more robust when handling log files that have no results. ........ r2632 | stevenknight | 2008-01-27 12:49:02 -0800 (Sun, 27 Jan 2008) | 2 lines Rotate label positions so they don't overwrite each other. ........ r2633 | stevenknight | 2008-01-27 16:21:17 -0800 (Sun, 27 Jan 2008) | 2 lines Extend vertical bars to graph top, not maximum X value. ........ r2634 | stevenknight | 2008-01-27 18:08:19 -0800 (Sun, 27 Jan 2008) | 2 lines Capture three configurations for timing various aspects of SCons. ........ r2635 | stevenknight | 2008-01-28 04:55:12 -0800 (Mon, 28 Jan 2008) | 2 lines Fix jar calls to use "tf" instead of "-t -f" for compatibility with Sun. ........ r2636 | stevenknight | 2008-01-28 12:49:58 -0800 (Mon, 28 Jan 2008) | 6 lines Refactor cut-and-paste tempdir_re() function into a common method in QMTest/TestSCons_time.py. In the refactored code, fix typo of os.path.relpath() where we meant os.path.realpath(), so we follow the /tmp -> /private/tmp symlink on Mac OS X. ........ r2637 | stevenknight | 2008-01-28 15:18:14 -0800 (Mon, 28 Jan 2008) | 5 lines Apple portability in the test for explicit "No such file" error messages from trying to fork()/exec() a non-existent file name. Refactor the tests for (non-)expected output in stderr so they're informative if they fail. ........ r2638 | stevenknight | 2008-01-28 17:54:29 -0800 (Mon, 28 Jan 2008) | 3 lines Make the test output deterministic by making the InstallAs() targets (file[23].out) depend on the Install() target (file1.out). ........ r2639 | stevenknight | 2008-01-28 21:37:38 -0800 (Mon, 28 Jan 2008) | 4 lines On Mac OS X, add -w to LINKFLAGS to suppress warnings about the directories we specify as -L arguments which don't actually exist. We just want to make sure that the right directory names show up. ........ r2640 | stevenknight | 2008-01-28 21:38:36 -0800 (Mon, 28 Jan 2008) | 3 lines On Mac OS X, the generated include file for C++ just tacks ".h" on the end of the generated .cpp file name. Define $YACCHXXFILESUFFIX accordingly. ........ r2641 | stevenknight | 2008-01-29 04:56:18 -0800 (Tue, 29 Jan 2008) | 3 lines Add the src/CHANGES.txt for the previous change (Mac OS X bison behavior). Add a "bison" application entity to the DocBook infrastructure. ........ r2642 | stevenknight | 2008-01-30 05:09:02 -0800 (Wed, 30 Jan 2008) | 5 lines Improve QT tests for Mac OS X: More general regular expression match for a "Generated moc file" warning. Copy libmyqt.dylib to the same directory as the "aaa" executable so it's found when we run it. ........ r2643 | stevenknight | 2008-01-30 05:19:23 -0800 (Wed, 30 Jan 2008) | 2 lines Skip the test of Java handling SWIG dependencies if swig isn't installed. ........ r2644 | stevenknight | 2008-01-30 06:44:30 -0800 (Wed, 30 Jan 2008) | 2 lines Remove left-over print statement. ........ r2645 | stevenknight | 2008-01-30 06:52:54 -0800 (Wed, 30 Jan 2008) | 2 lines Mac OS X fix: use .dylib, not .so, in the list of "weird suffixes" we test. ........
Diffstat (limited to 'test')
-rw-r--r--test/Actions/function.py192
-rw-r--r--test/CPPDEFINES/basic.py64
-rw-r--r--test/CPPDEFINES/live.py (renamed from test/CPPDEFINES.py)45
-rw-r--r--test/CPPDEFINES/scan.py181
-rw-r--r--test/CPPDEFINES/undefined.py45
-rw-r--r--test/CPPPATH/absolute-path.py75
-rw-r--r--test/CPPPATH/function-expansion.py137
-rw-r--r--test/CPPPATH/list-expansion.py132
-rw-r--r--test/Configure/Builder-call.py4
-rw-r--r--test/D/DMD.py (renamed from test/DMD.py)0
-rw-r--r--test/D/Scanner.py144
-rw-r--r--test/Errors/SyntaxError.py4
-rw-r--r--test/Errors/execute-a-directory.py109
-rw-r--r--test/Errors/non-executable-file.py103
-rw-r--r--test/Errors/nonexistent-executable.py107
-rw-r--r--test/Errors/permission-denied.py64
-rw-r--r--test/Install/option--install-sandbox.py9
-rw-r--r--test/Interactive/Alias.py85
-rw-r--r--test/Interactive/Default-None.py96
-rw-r--r--test/Interactive/Default.py86
-rw-r--r--test/Interactive/added-include.py118
-rw-r--r--test/Interactive/basic.py84
-rw-r--r--test/Interactive/cache-debug.py117
-rw-r--r--test/Interactive/cache-disable.py115
-rw-r--r--test/Interactive/cache-force.py113
-rw-r--r--test/Interactive/cache-show.py115
-rw-r--r--test/Interactive/clean.py105
-rw-r--r--test/Interactive/exit.py64
-rw-r--r--test/Interactive/help.py85
-rw-r--r--test/Interactive/implicit-BuildDir.py142
-rw-r--r--test/Interactive/option--Q.py83
-rw-r--r--test/Interactive/option-i.py106
-rw-r--r--test/Interactive/option-j.py164
-rw-r--r--test/Interactive/option-k.py108
-rw-r--r--test/Interactive/option-n.py79
-rw-r--r--test/Interactive/option-s.py79
-rw-r--r--test/Interactive/repeat-line.py87
-rw-r--r--test/Interactive/shell.py116
-rw-r--r--test/Interactive/taskmastertrace.py90
-rw-r--r--test/Interactive/tree.py91
-rw-r--r--test/Interactive/unknown-command.py66
-rw-r--r--test/Interactive/version.py84
-rw-r--r--test/Java/JAR.py20
-rw-r--r--test/Java/JARCHDIR.py17
-rw-r--r--test/Java/JARFLAGS.py23
-rw-r--r--test/Java/JAVABOOTCLASSPATH.py17
-rw-r--r--test/Java/JAVACFLAGS.py9
-rw-r--r--test/Java/JAVACLASSPATH.py17
-rw-r--r--test/Java/JAVAH.py25
-rw-r--r--test/Java/JAVASOURCEPATH.py9
-rw-r--r--test/Java/Java-1.4.py33
-rw-r--r--test/Java/Java-1.5.py16
-rw-r--r--test/Java/Java-1.6.py16
-rw-r--r--test/Java/RMIC.py40
-rw-r--r--test/Java/RMICCOM.py6
-rw-r--r--test/Java/RMICCOMSTR.py6
-rw-r--r--test/Java/multi-step.py18
-rw-r--r--test/Java/no-JARCHDIR.py122
-rw-r--r--test/Java/source-files.py9
-rw-r--r--test/Java/swig-dependencies.py29
-rw-r--r--test/Libs/LIBPATH.py (renamed from test/LIBPATH.py)0
-rw-r--r--test/Libs/LIBPREFIX.py (renamed from test/LIBPREFIX.py)0
-rw-r--r--test/Libs/LIBPREFIXES.py (renamed from test/LIBPREFIXES.py)0
-rw-r--r--test/Libs/LIBS.py (renamed from test/LIBS.py)0
-rw-r--r--test/Libs/LIBSUFFIX.py (renamed from test/LIBSUFFIX.py)0
-rw-r--r--test/Libs/LIBSUFFIXES.py (renamed from test/LIBSUFFIXES.py)0
-rw-r--r--test/Libs/Library.py (renamed from test/Library.py)0
-rw-r--r--test/Libs/SHLIBPREFIX.py (renamed from test/SHLIBPREFIX.py)0
-rw-r--r--test/Libs/SHLIBSUFFIX.py (renamed from test/SHLIBSUFFIX.py)0
-rw-r--r--test/Libs/SharedLibrary.py (renamed from test/SharedLibrary.py)0
-rw-r--r--test/Libs/SharedLibraryIxes.py261
-rw-r--r--test/LoadableModule.py3
-rw-r--r--test/MSVC/pdb-manifest.py81
-rw-r--r--test/QT/moc-from-header.py4
-rw-r--r--test/QT/warnings.py7
-rw-r--r--test/Repository/Java.py16
-rw-r--r--test/Repository/JavaH.py22
-rw-r--r--test/Repository/LIBPATH.py7
-rw-r--r--test/Repository/RMIC.py88
-rw-r--r--test/SWIG/module-parens.py102
-rw-r--r--test/Scanner/generated.py8
-rw-r--r--test/TEX/build_dir_dup0.py257
-rw-r--r--test/TEX/multi-run.py88
-rw-r--r--test/YACC/live.py10
-rw-r--r--test/build-errors.py223
-rw-r--r--test/builderrors.py16
-rw-r--r--test/import.py1
-rw-r--r--test/option-k.py168
-rw-r--r--test/option/debug-includes.py9
-rw-r--r--test/option/debug-memoizer.py32
-rw-r--r--test/option/stack-size.py357
-rw-r--r--test/scons-time/func/file.py27
-rw-r--r--test/scons-time/mem/file.py9
-rw-r--r--test/scons-time/obj/file.py9
-rw-r--r--test/scons-time/run/aegis.py17
-rw-r--r--test/scons-time/run/config/archive_list.py6
-rw-r--r--test/scons-time/run/option/quiet.py21
-rw-r--r--test/scons-time/run/option/verbose.py21
-rw-r--r--test/scons-time/run/subversion.py17
-rw-r--r--test/scons-time/time/empty.py91
-rw-r--r--test/scons-time/time/file.py9
-rw-r--r--test/scons-time/time/no-result.py75
-rw-r--r--test/subclassing.py37
-rw-r--r--test/timestamp-fallback.py9
104 files changed, 5734 insertions, 699 deletions
diff --git a/test/Actions/function.py b/test/Actions/function.py
new file mode 100644
index 0000000..00aa688
--- /dev/null
+++ b/test/Actions/function.py
@@ -0,0 +1,192 @@
+#!/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 TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+#
+# Test that the signature of function action includes all the
+# necessary pieces.
+#
+
+test.write('SConstruct', r"""
+import re
+
+import SCons.Action
+import SCons.Builder
+
+options = Options()
+options.AddOptions(
+ ('header', 'Header string (default cell argument)', 'Head:'),
+ ('trailer', 'Trailer string (default cell argument)', 'Tail'),
+ ('NbDeps', 'Number of dependencies', '2'),
+ ('separator', 'Separator for the dependencies (function constant)', ':'),
+ ('closure_cell_value', 'Value of a closure cell', '25'),
+ ('b', 'Value of b (value default argument', '7'),
+ ('regexp', 'Regexp (object as a default argument', 'a(a*)'),
+ ('docstring', 'Docstring', 'docstring'),
+ ('extracode', 'Extra code for the builder function', ''),
+ ('extraarg', 'Extra arg builder function', ''),
+ ('nestedfuncexp', 'Expression for the nested function', 'xxx - b'),
+)
+
+optEnv = Environment(options=options, tools=[])
+
+r = re.compile(optEnv['regexp'])
+
+toto = \
+r'''
+def toto(header='%(header)s', trailer='%(trailer)s'):
+ xxx = %(closure_cell_value)s
+ def writeDeps(target, source, env, b=%(b)s, r=r %(extraarg)s ,
+ header=header, trailer=trailer, xxx=xxx):
+ """+'"""%(docstring)s"""'+"""
+ def foo(b=b, xxx=xxx):
+ return %(nestedfuncexp)s
+ f = open(str(target[0]),'wb')
+ f.write(header)
+ for d in env['ENVDEPS']:
+ f.write(d+'%(separator)s')
+ f.write(trailer+'\\n')
+ f.write(str(foo())+'\\n')
+ f.write(r.match('aaaa').group(1)+'\\n')
+ %(extracode)s
+ try:
+ f.write(str(xarg)+'\\n')
+ except NameError:
+ pass
+ f.close()
+
+ return writeDeps
+'''
+
+exec( toto % optEnv )
+
+genHeaderBld = SCons.Builder.Builder(
+ action = SCons.Action.Action(
+ toto(),
+ 'Generating $TARGET',
+ varlist=['ENVDEPS']
+ ),
+ suffix = '.gen.h'
+ )
+
+env = Environment()
+env.Append(BUILDERS = {'GenHeader' : genHeaderBld})
+
+envdeps = map(str, range(int(optEnv['NbDeps'])))
+
+env.GenHeader('Out', None, ENVDEPS=envdeps)
+""")
+
+
+rebuildstr = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+Generating Out.gen.h
+scons: done building targets.
+"""
+
+nobuildstr = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+scons: `.' is up to date.
+scons: done building targets.
+"""
+
+def runtest( arguments, expectedOutFile, expectedRebuild=True):
+ test.run(arguments=arguments,
+ stdout=expectedRebuild and rebuildstr or nobuildstr)
+ test.must_match('Out.gen.h', expectedOutFile)
+
+ # Should not be rebuild when ran a second time with the same
+ # arguments.
+
+ test.run(arguments = arguments, stdout=nobuildstr)
+ test.must_match('Out.gen.h', expectedOutFile)
+
+
+# Original build.
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing a docstring should not cause a rebuild
+runtest('docstring=ThisBuilderDoesXAndY', """Head:0:1:Tail\n18\naaa\n""", False)
+runtest('docstring=SuperBuilder', """Head:0:1:Tail\n18\naaa\n""", False)
+runtest('docstring=', """Head:0:1:Tail\n18\naaa\n""", False)
+
+# Changing a variable listed in the varlist should cause a rebuild
+runtest('NbDeps=3', """Head:0:1:2:Tail\n18\naaa\n""")
+runtest('NbDeps=4', """Head:0:1:2:3:Tail\n18\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing the function code should cause a rebuild
+runtest('extracode=f.write("XX\\n")', """Head:0:1:Tail\n18\naaa\nXX\n""")
+runtest('extracode=a=2', """Head:0:1:Tail\n18\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing a constant used in the function code should cause a rebuild
+runtest('separator=,', """Head:0,1,Tail\n18\naaa\n""")
+runtest('separator=;', """Head:0;1;Tail\n18\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing the code of a nested function should cause a rebuild
+runtest('nestedfuncexp=b-xxx', """Head:0:1:Tail\n-18\naaa\n""")
+runtest('nestedfuncexp=b+xxx', """Head:0:1:Tail\n32\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Adding an extra argument should cause a rebuild.
+runtest('extraarg=,xarg=2', """Head:0:1:Tail\n18\naaa\n2\n""")
+runtest('extraarg=,xarg=5', """Head:0:1:Tail\n18\naaa\n5\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing the value of a default argument should cause a rebuild
+# case 1: a value
+runtest('b=0', """Head:0:1:Tail\n25\naaa\n""")
+runtest('b=9', """Head:0:1:Tail\n16\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# case 2: an object
+runtest('regexp=(aaaa)', """Head:0:1:Tail\n18\naaaa\n""")
+runtest('regexp=aa(a+)', """Head:0:1:Tail\n18\naa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# Changing the value of a closure cell value should cause a rebuild
+# case 1: a value
+runtest('closure_cell_value=32', """Head:0:1:Tail\n25\naaa\n""")
+runtest('closure_cell_value=7', """Head:0:1:Tail\n0\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+# case 2: a default argument
+runtest('header=MyHeader:', """MyHeader:0:1:Tail\n18\naaa\n""")
+runtest('trailer=MyTrailer', """Head:0:1:MyTrailer\n18\naaa\n""")
+runtest('', """Head:0:1:Tail\n18\naaa\n""")
+
+test.pass_test()
diff --git a/test/CPPDEFINES/basic.py b/test/CPPDEFINES/basic.py
new file mode 100644
index 0000000..5c302c3
--- /dev/null
+++ b/test/CPPDEFINES/basic.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 basic use of CPPPDEFINES with various data types.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+test_list = [
+ 'xyz',
+ ['x', 'y', 'z'],
+ ['x', ['y', 123], 'z', ('int', '$INTEGER')],
+ { 'c' : 3, 'b': None, 'a' : 1 },
+]
+env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0)
+for i in test_list:
+ print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')
+env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1)
+for i in test_list:
+ print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')
+""")
+
+expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
+ read_str = """\
+-Dxyz
+-Dx -Dy -Dz
+-Dx -Dy=123 -Dz -Dint=0
+-Da=1 -Db -Dc=3
+|xyz|
+|x| |y| |z|
+|x| |y=123| |z| |int=1|
+|a=1| |b| |c=3|
+""")
+
+test.run(arguments = '.', stdout=expect)
+
+test.pass_test()
diff --git a/test/CPPDEFINES.py b/test/CPPDEFINES/live.py
index c38f857..7a169e8 100644
--- a/test/CPPDEFINES.py
+++ b/test/CPPDEFINES/live.py
@@ -25,56 +25,13 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-XXX Put a description of the test here.
+Verify basic use of CPPDEFINES with live compilation.
"""
-import string
-
import TestSCons
test = TestSCons.TestSCons()
-# Make sure $_CPPDEFFLAGS doesn't barf when CPPDEFINES isn't defined.
-test.write('SConstruct', """\
-env = Environment()
-print env.subst('$_CPPDEFFLAGS')
-""")
-
-expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
- read_str = "\n")
-
-test.run(arguments = '.', stdout=expect)
-
-# Test CPPDEFINES as a string and a list.
-test.write('SConstruct', """\
-test_list = [
- 'xyz',
- ['x', 'y', 'z'],
- ['x', ['y', 123], 'z', ('int', '$INTEGER')],
- { 'c' : 3, 'b': None, 'a' : 1 },
-]
-env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0)
-for i in test_list:
- print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')
-env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1)
-for i in test_list:
- print env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS')
-""")
-
-expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
- read_str = """\
--Dxyz
--Dx -Dy -Dz
--Dx -Dy=123 -Dz -Dint=0
--Da=1 -Db -Dc=3
-|xyz|
-|x| |y| |z|
-|x| |y=123| |z| |int=1|
-|a=1| |b| |c=3|
-""")
-
-test.run(arguments = '.', stdout=expect)
-
test.write('SConstruct', """\
foo = Environment(CPPDEFINES = ['FOO', ('VAL', '$VALUE')], VALUE=7)
bar = Environment(CPPDEFINES = {'BAR':None, 'VAL':8})
diff --git a/test/CPPDEFINES/scan.py b/test/CPPDEFINES/scan.py
new file mode 100644
index 0000000..c9b60c3
--- /dev/null
+++ b/test/CPPDEFINES/scan.py
@@ -0,0 +1,181 @@
+#!/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 use of the Scanner that evaluates CPP lines works as expected.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+m = 'Scanner evaluation of CPP lines not yet supported; skipping test.\n'
+test.skip_test(m)
+
+f1_exe = 'f1' + TestSCons._exe
+f2_exe = 'f2' + TestSCons._exe
+f3_exe = 'f3' + TestSCons._exe
+f4_exe = 'f4' + TestSCons._exe
+
+test.write('SConstruct', """\
+env = Environment(CPPPATH = ['.'])
+
+f1 = env.Object('f1', 'fff.c', CPPDEFINES = ['F1'])
+f2 = env.Object('f2', 'fff.c', CPPDEFINES = [('F2', 1)])
+f3 = env.Object('f3', 'fff.c', CPPDEFINES = {'F3':None})
+f4 = env.Object('f4', 'fff.c', CPPDEFINES = {'F4':1})
+
+env.Program('f1', ['prog.c', f1])
+env.Program('f2', ['prog.c', f2])
+env.Program('f3', ['prog.c', f3])
+env.Program('f4', ['prog.c', f4])
+""")
+
+test.write('f1.h', """
+#define STRING "F1"
+""")
+
+test.write('f2.h', """
+#define STRING "F2"
+""")
+
+test.write('f3.h', """
+#define STRING "F3"
+""")
+
+test.write('f4.h', """
+#define STRING "F4"
+""")
+
+test.write('fff.c', """
+#ifdef F1
+#include <f1.h>
+#endif
+#if F2
+#include <f2.h>
+#endif
+#ifdef F3
+#include <f3.h>
+#endif
+#ifdef F4
+#include <f4.h>
+#endif
+
+char *
+foo(void)
+{
+ return (STRING);
+}
+""")
+
+
+test.write('prog.c', r"""
+#include <stdio.h>
+#include <stdlib.h>
+
+extern char *foo(void);
+
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("prog.c: %s\n", foo());
+ exit (0);
+}
+""")
+
+
+
+test.run(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n")
+
+
+
+test.write('f1.h', """
+#define STRING "F1 again"
+""")
+
+test.up_to_date(arguments = '%(f2_exe)s %(f3_exe)s %(f4_exe)s' % locals())
+
+test.not_up_to_date(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n")
+
+
+
+test.write('f2.h', """
+#define STRING "F2 again"
+""")
+
+test.up_to_date(arguments = '%(f1_exe)s %(f3_exe)s %(f4_exe)s' % locals())
+
+test.not_up_to_date(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n")
+
+
+
+test.write('f3.h', """
+#define STRING "F3 again"
+""")
+
+test.up_to_date(arguments = '%(f1_exe)s %(f2_exe)s %(f4_exe)s' % locals())
+
+test.not_up_to_date(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3 again\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n")
+
+
+
+test.write('f4.h', """
+#define STRING "F4 again"
+""")
+
+test.up_to_date(arguments = '%(f1_exe)s %(f2_exe)s %(f3_exe)s' % locals())
+
+test.not_up_to_date(arguments = '.')
+
+test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n")
+test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n")
+test.run(program = test.workpath('f3'), stdout = "prog.c: F3 again\n")
+test.run(program = test.workpath('f4'), stdout = "prog.c: F4 again\n")
+
+
+
+test.pass_test()
diff --git a/test/CPPDEFINES/undefined.py b/test/CPPDEFINES/undefined.py
new file mode 100644
index 0000000..b6b8b44
--- /dev/null
+++ b/test/CPPDEFINES/undefined.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 $_CPPDEFFLAGS doesn't barf when CPPDEFINES isn't defined.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+print env.subst('$_CPPDEFFLAGS')
+""")
+
+expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
+ read_str = "\n")
+
+test.run(arguments = '.', stdout=expect)
+
+test.pass_test()
diff --git a/test/CPPPATH/absolute-path.py b/test/CPPPATH/absolute-path.py
new file mode 100644
index 0000000..9adb206
--- /dev/null
+++ b/test/CPPPATH/absolute-path.py
@@ -0,0 +1,75 @@
+#!/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 #include a file with an absolute path name. (Which
+is not strictly a test of using $CPPPATH, but it's in the ball park...)
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('include', 'work')
+
+inc_h = test.workpath('include', 'inc.h')
+does_not_exist_h = test.workpath('include', 'does_not_exist.h')
+
+test.write(['work', 'SConstruct'], """\
+Program('prog.c')
+""")
+
+test.write(['work', 'prog.c'], """\
+#include <stdio.h>
+#include "%(inc_h)s"
+#if 0
+#include "%(does_not_exist_h)s"
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("%%s\\n", STRING);
+ return 0;
+}
+""" % locals())
+
+test.write(['include', 'inc.h'], """\
+#define STRING "include/inc.h 1\\n"
+""")
+
+test.run(chdir = 'work', arguments = '.')
+
+test.up_to_date(chdir = 'work', arguments = '.')
+
+test.write(['include', 'inc.h'], """\
+#define STRING "include/inc.h 2\\n"
+""")
+
+test.not_up_to_date(chdir = 'work', arguments = '.')
+
+test.pass_test()
diff --git a/test/CPPPATH/function-expansion.py b/test/CPPPATH/function-expansion.py
new file mode 100644
index 0000000..7c80f22
--- /dev/null
+++ b/test/CPPPATH/function-expansion.py
@@ -0,0 +1,137 @@
+#!/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 expansion of construction variables whose values are functions
+(that return lists that contain Nodes, even) works as expected within
+a $CPPPATH list definition.
+
+This used to cause TypeErrors when the _concat expansion tried to
+join the Nodes with the strings.
+
+Test courtesy Konstantin Bozhikov.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('list_inc1',
+ 'list_inc2',
+ 'inc1',
+ 'inc2',
+ 'inc3',
+ ['inc3', 'subdir'])
+
+test.write('SConstruct', """\
+env = Environment()
+def my_cpppaths( target, source, env, for_signature ):
+ return [ Dir('list_inc1'), Dir('list_inc2') ]
+
+env = Environment( CPPPATH = [Dir('inc1'), '$INC2', '$INC3/subdir', '$MY_CPPPATHS' ],
+ INC2 = Dir('inc2'),
+ INC3 = Dir('inc3'),
+ MY_CPPPATHS = my_cpppaths )
+
+env.Program('prog.c')
+""")
+
+test.write('prog.c', """\
+#include <stdio.h>
+#include <stdlib.h>
+#include "string_list_1.h"
+#include "string_list_2.h"
+#include "string_1.h"
+#include "string_2.h"
+#include "string_3.h"
+
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("prog.c\\n");
+ printf("%s\\n", STRING_LIST_1);
+ printf("%s\\n", STRING_LIST_2);
+ printf("%s\\n", STRING_1);
+ printf("%s\\n", STRING_2);
+ printf("%s\\n", STRING_3);
+ exit (0);
+}
+""")
+
+test.write(['list_inc1', 'string_list_1.h'], """\
+#define STRING_LIST_1 "list_inc1/string_list_1.h"
+""")
+
+test.write(['list_inc2', 'string_list_2.h'], """\
+#define STRING_LIST_2 "list_inc2/string_list_2.h"
+""")
+
+test.write(['inc1', 'string_1.h'], """\
+#define STRING_1 "inc1/string_1.h"
+""")
+
+test.write(['inc2', 'string_2.h'], """\
+#define STRING_2 "inc2/string_2.h"
+""")
+
+test.write(['inc3', 'subdir', 'string_3.h'], """\
+#define STRING_3 "inc3/subdir/string_3.h"
+""")
+
+test.run()
+
+test.up_to_date(arguments = '.')
+
+expect = """\
+prog.c
+list_inc1/string_list_1.h
+list_inc2/string_list_2.h
+inc1/string_1.h
+inc2/string_2.h
+inc3/subdir/string_3.h
+"""
+
+test.run(program = test.workpath('prog' + TestSCons._exe), stdout=expect)
+
+test.write(['inc3', 'subdir', 'string_3.h'], """\
+#define STRING_3 "inc3/subdir/string_3.h 2"
+""")
+
+test.not_up_to_date(arguments = '.')
+
+expect = """\
+prog.c
+list_inc1/string_list_1.h
+list_inc2/string_list_2.h
+inc1/string_1.h
+inc2/string_2.h
+inc3/subdir/string_3.h 2
+"""
+
+test.run(program = test.workpath('prog' + TestSCons._exe), stdout=expect)
+
+test.pass_test()
diff --git a/test/CPPPATH/list-expansion.py b/test/CPPPATH/list-expansion.py
new file mode 100644
index 0000000..7e5326f
--- /dev/null
+++ b/test/CPPPATH/list-expansion.py
@@ -0,0 +1,132 @@
+#!/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 expansion of construction variables whose values are
+lists works as expected within a $CPPPATH list definition.
+
+Previously, the stringification of the expansion of the individual
+variables would turn a list like ['sub1', 'sub2'] below into "-Isub1 sub2"
+on the command line.
+
+Test case courtesy Daniel Svensson.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('sub1', 'sub2', 'sub3', 'sub4')
+
+test.write('SConstruct', """\
+class _inc_test:
+ def __init__(self, name):
+ self.name = name
+
+ def __call__(self, target, source, env, for_signature):
+ return env.something[self.name]
+
+env = Environment()
+
+env.something = {}
+env.something['test'] = ['sub1', 'sub2']
+
+env['INC_PATHS1'] = _inc_test
+
+env['INC_PATHS2'] = ['sub3', 'sub4']
+
+env.Append(CPPPATH = ['${INC_PATHS1("test")}', '$INC_PATHS2'])
+env.Program('test', 'test.c')
+""")
+
+test.write('test.c', """\
+#include <stdio.h>
+#include <stdlib.h>
+#include "string1.h"
+#include "string2.h"
+#include "string3.h"
+#include "string4.h"
+
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ printf("test.c\\n");
+ printf("%s\\n", STRING1);
+ printf("%s\\n", STRING2);
+ printf("%s\\n", STRING3);
+ printf("%s\\n", STRING4);
+ exit (0);
+}
+""")
+
+test.write(['sub1', 'string1.h'], """\
+#define STRING1 "sub1/string1.h"
+""")
+
+test.write(['sub2', 'string2.h'], """\
+#define STRING2 "sub2/string2.h"
+""")
+
+test.write(['sub3', 'string3.h'], """\
+#define STRING3 "sub3/string3.h"
+""")
+
+test.write(['sub4', 'string4.h'], """\
+#define STRING4 "sub4/string4.h"
+""")
+
+test.run()
+
+test.up_to_date(arguments = '.')
+
+expect = """\
+test.c
+sub1/string1.h
+sub2/string2.h
+sub3/string3.h
+sub4/string4.h
+"""
+
+test.run(program = test.workpath('test' + TestSCons._exe), stdout=expect)
+
+test.write(['sub2', 'string2.h'], """\
+#define STRING2 "sub2/string2.h 2"
+""")
+
+test.not_up_to_date(arguments = '.')
+
+expect = """\
+test.c
+sub1/string1.h
+sub2/string2.h 2
+sub3/string3.h
+sub4/string4.h
+"""
+
+test.run(program = test.workpath('test' + TestSCons._exe), stdout=expect)
+
+test.pass_test()
diff --git a/test/Configure/Builder-call.py b/test/Configure/Builder-call.py
index a6f2fa5..1ce114c 100644
--- a/test/Configure/Builder-call.py
+++ b/test/Configure/Builder-call.py
@@ -35,7 +35,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-test.write('cmd.py', r"""
+test.write('mycommand.py', r"""
import sys
sys.stderr.write( 'Hello World on stderr\n' )
sys.stdout.write( 'Hello World on stdout\n' )
@@ -48,7 +48,7 @@ def CustomTest(*args):
return 0
conf = env.Configure(custom_tests = {'MyTest' : CustomTest})
if not conf.MyTest():
- env.Command("hello", [], '%(_python_)s cmd.py $TARGET')
+ env.Command("hello", [], '%(_python_)s mycommand.py $TARGET')
env = conf.Finish()
""" % locals())
diff --git a/test/DMD.py b/test/D/DMD.py
index 8b443f8..8b443f8 100644
--- a/test/DMD.py
+++ b/test/D/DMD.py
diff --git a/test/D/Scanner.py b/test/D/Scanner.py
new file mode 100644
index 0000000..5c69820
--- /dev/null
+++ b/test/D/Scanner.py
@@ -0,0 +1,144 @@
+#!/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 D scanner can return multiple modules imported by
+a single statement.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+_obj = TestSCons._obj
+
+dmd = test.where_is('dmd')
+if not dmd:
+ test.skip_test("Could not find 'dmd'; skipping test.\n")
+
+test.subdir(['p'])
+
+test.write('SConstruct', """
+env = Environment()
+env.Program('test1.d')
+env.Program('test2.d')
+""")
+
+test.write(['test1.d'], """\
+import module1;
+import module2;
+import module3;
+import p.submodule1;
+import p.submodule2;
+
+int main() {
+ return 0;
+}
+""")
+
+test.write(['test2.d'], """\
+import
+ module1,
+ module2,
+ module3;
+import
+ p.submodule1,
+ p.submodule2;
+
+int main() {
+ return 0;
+}
+""")
+
+test.write(['ignored.d'], """\
+module ignored;
+
+int something;
+""")
+
+test.write(['module1.d'], """\
+module module1;
+
+int something;
+""")
+
+test.write(['module2.d'], """\
+module module2;
+
+int something;
+""")
+
+test.write(['module3.di'], """\
+module module3;
+
+int something;
+""")
+
+test.write(['p', 'ignored.d'], """\
+module p.ignored;
+
+int something;
+""")
+
+test.write(['p', 'submodule1.d'], """\
+module p.submodule1;
+
+int something;
+""")
+
+test.write(['p', 'submodule2.d'], """\
+module p.submodule2;
+
+int something;
+""")
+
+arguments = 'test1%(_obj)s test2%(_obj)s' % locals()
+
+test.run(arguments = arguments)
+
+test.up_to_date(arguments = arguments)
+
+test.write(['module2.d'], """\
+module module2;
+
+int something_else;
+""")
+
+test.not_up_to_date(arguments = arguments)
+
+test.up_to_date(arguments = arguments)
+
+test.write(['p', 'submodule2.d'], """\
+module p.submodule2;
+
+int something_else;
+""")
+
+test.not_up_to_date(arguments = arguments)
+
+test.up_to_date(arguments = arguments)
+
+test.pass_test()
diff --git a/test/Errors/SyntaxError.py b/test/Errors/SyntaxError.py
index b9ff1ff..956caa7 100644
--- a/test/Errors/SyntaxError.py
+++ b/test/Errors/SyntaxError.py
@@ -37,8 +37,10 @@ test.write('SConstruct', """
a ! x
""")
+# It looks like vanilla Python 2.2 is the only version that
+# puts "<string>" here in place of the file name.
test.run(stdout = "scons: Reading SConscript files ...\n",
- stderr = """ File ".+SConstruct", line 2
+ stderr = """ File "(.+SConstruct|<string>)", line 2
a ! x
diff --git a/test/Errors/execute-a-directory.py b/test/Errors/execute-a-directory.py
new file mode 100644
index 0000000..bcdcb7c
--- /dev/null
+++ b/test/Errors/execute-a-directory.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__"
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+not_executable = test.workpath("not_executable")
+
+test.write(not_executable, "\n")
+
+test.write("f3.in", "\n")
+
+test.write('SConstruct', r"""
+bld = Builder(action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = { 'bld' : bld })
+env.bld(target = 'f3', source = 'f3.in')
+""" % string.replace(test.workdir, '\\', '\\\\'))
+
+test.run(arguments='.',
+ stdout = test.wrap_stdout("%s f3.in f3\n" % test.workdir, error=1),
+ stderr = None,
+ status = 2)
+
+bad_command = """\
+Bad command or file name
+"""
+
+unrecognized = """\
+'%s' is not recognized as an internal or external command,
+operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+unspecified = """\
+The name specified is not recognized as an
+internal or external command, operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+cannot_execute = """\
+%s: cannot execute
+scons *** [%s] Error 126
+"""
+
+Permission_denied = """\
+%s: Permission denied
+scons: *** [%s] Error 126
+"""
+
+permission_denied = """\
+%s: permission denied
+scons: *** [%s] Error 126
+"""
+
+is_a_directory = """\
+%s: is a directory
+scons: *** [%s] Error 126
+"""
+
+test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
+if os.name == 'nt':
+ errs = [
+ bad_command,
+ unrecognized % (test.workdir, 'f3'),
+ unspecified % 'f3'
+ ]
+ test.fail_test(not test.stderr() in errs)
+else:
+ errs = [
+ cannot_execute % (not_executable, 'f3'),
+ is_a_directory % (test.workdir, 'f3'),
+ Permission_denied % (test.workdir, 'f3'),
+ Permission_denied % (test.workdir, 'f3'),
+ ]
+ error_message_not_found = 1
+ for err in errs:
+ if string.find(test.stderr(), err) != -1:
+ error_message_not_found = None
+ break
+ test.fail_test(error_message_not_found)
+
+test.pass_test()
diff --git a/test/Errors/non-executable-file.py b/test/Errors/non-executable-file.py
new file mode 100644
index 0000000..d6e018b
--- /dev/null
+++ b/test/Errors/non-executable-file.py
@@ -0,0 +1,103 @@
+#!/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
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+not_executable = test.workpath("not_executable")
+
+test.write(not_executable, "\n")
+
+test.write("f1.in", "\n")
+
+bad_command = """\
+Bad command or file name
+"""
+
+unrecognized = """\
+'%s' is not recognized as an internal or external command,
+operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+unspecified = """\
+The name specified is not recognized as an
+internal or external command, operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+cannot_execute = """\
+%s: cannot execute
+scons *** [%s] Error 126
+"""
+
+Permission_denied = """\
+%s: Permission denied
+scons: *** [%s] Error 126
+"""
+
+permission_denied = """\
+%s: permission denied
+scons: *** [%s] Error 126
+"""
+
+test.write('SConstruct', r"""
+bld = Builder(action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = { 'bld': bld })
+env.bld(target = 'f1', source = 'f1.in')
+""" % string.replace(not_executable, '\\', '\\\\'))
+
+test.run(arguments='.',
+ stdout = test.wrap_stdout("%s f1.in f1\n" % not_executable, error=1),
+ stderr = None,
+ status = 2)
+
+test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
+if os.name == 'nt':
+ errs = [
+ bad_command,
+ unrecognized % (not_executable, 'f1'),
+ unspecified % 'f1'
+ ]
+ test.fail_test(not test.stderr() in errs)
+else:
+ errs = [
+ cannot_execute % (not_executable, 'f1'),
+ Permission_denied % (not_executable, 'f1'),
+ permission_denied % (not_executable, 'f1'),
+ ]
+ error_message_not_found = 1
+ for err in errs:
+ if string.find(test.stderr(), err) != -1:
+ error_message_not_found = None
+ break
+ test.fail_test(error_message_not_found)
+
+test.pass_test()
diff --git a/test/Errors/nonexistent-executable.py b/test/Errors/nonexistent-executable.py
new file mode 100644
index 0000000..b2a9557
--- /dev/null
+++ b/test/Errors/nonexistent-executable.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+no_such_file = test.workpath("no_such_file")
+
+test.write("f1.in", "\n")
+
+test.write('SConstruct', r"""
+bld = Builder(action = '%s $SOURCES $TARGET')
+env = Environment(BUILDERS = { 'bld' : bld })
+env.bld(target = 'f1', source = 'f1.in')
+""" % string.replace(no_such_file, '\\', '\\\\'))
+
+test.run(arguments='.',
+ stdout = test.wrap_stdout("%s f1.in f1\n" % no_such_file, error=1),
+ stderr = None,
+ status = 2)
+
+bad_command = """\
+Bad command or file name
+"""
+
+unrecognized = """\
+'%s' is not recognized as an internal or external command,
+operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+unspecified = """\
+The name specified is not recognized as an
+internal or external command, operable program or batch file.
+scons: *** [%s] Error 1
+"""
+
+not_found_1 = """
+sh: %s: not found
+scons: *** [%s] Error 1
+"""
+
+not_found_2 = """
+sh: %s: not found
+scons: *** [%s] Error 1
+"""
+
+not_found_127 = """\
+sh: %s: not found
+scons: *** [%s] Error 127
+"""
+
+No_such = """\
+%s: No such file or directory
+scons: *** [%s] Error 127
+"""
+
+test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
+if os.name == 'nt':
+ errs = [
+ bad_command,
+ unrecognized % (no_such_file, 'f1'),
+ unspecified % 'f1'
+ ]
+ test.fail_test(not test.stderr() in errs)
+else:
+ errs = [
+ not_found_1 % (no_such_file, 'f1'),
+ not_found_2 % (no_such_file, 'f1'),
+ not_found_127 % (no_such_file, 'f1'),
+ No_such % (no_such_file, 'f1'),
+ ]
+ error_message_not_found = 1
+ for err in errs:
+ if string.find(test.stderr(), err) != -1:
+ error_message_not_found = None
+ break
+ test.fail_test(error_message_not_found)
+
+test.pass_test()
diff --git a/test/Errors/permission-denied.py b/test/Errors/permission-denied.py
new file mode 100644
index 0000000..05d1e9d
--- /dev/null
+++ b/test/Errors/permission-denied.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__"
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', r"""
+env = Environment()
+env.Command('test.out', 'test.in', Copy('$TARGET', '$SOURCE'))
+env.InstallAs('test2.out', 'test.out')
+# Mark test2.out as precious so we'll handle the exception in
+# FunctionAction() rather than when the target is cleaned before building.
+env.Precious('test2.out')
+env.Default('test2.out')
+""")
+
+test.write('test.in', "test.in 1\n")
+
+test.run(arguments = '.')
+
+test.write('test.in', "test.in 2\n")
+
+test.writable('test2.out', 0)
+f = open(test.workpath('test2.out'))
+
+test.run(arguments = '.',
+ stderr = None,
+ status = 2)
+
+f.close()
+test.writable('test2.out', 1)
+
+test.description_set("Incorrect STDERR:\n%s" % test.stderr())
+errs = [
+ "scons: *** [test2.out] test2.out: Permission denied\n",
+ "scons: *** [test2.out] test2.out: permission denied\n",
+]
+test.fail_test(test.stderr() not in errs)
+
+test.pass_test()
diff --git a/test/Install/option--install-sandbox.py b/test/Install/option--install-sandbox.py
index 4cf9310..38a7915 100644
--- a/test/Install/option--install-sandbox.py
+++ b/test/Install/option--install-sandbox.py
@@ -48,9 +48,10 @@ file1_out = target+os.path.join( target, destdir, 'file1.out' )
#
test.write('SConstruct', r"""
env = Environment(SUBDIR='subdir')
-env.Install(r'%(destdir)s', 'file1.out')
-env.InstallAs(['file2.out', r'%(_SUBDIR_file3_out)s'],
- ['file2.in', r'%(_SUBDIR_file3_in)s'])
+f1 = env.Install(r'%(destdir)s', 'file1.out')
+f2 = env.InstallAs(['file2.out', r'%(_SUBDIR_file3_out)s'],
+ ['file2.in', r'%(_SUBDIR_file3_in)s'])
+env.Depends(f2, f1)
""" % locals())
test.write('file1.out', "file1.out\n")
@@ -58,9 +59,9 @@ test.write('file2.in', "file2.in\n")
test.write(['subdir', 'file3.in'], "subdir/file3.in\n")
expect = test.wrap_stdout("""\
+Install file: "file1.out" as "%(file1_out)s"
Install file: "file2.in" as "%(target_file2_out)s"
Install file: "%(subdir_file3_in)s" as "%(target_subdir_file3_out)s"
-Install file: "file1.out" as "%(file1_out)s"
""" % locals())
test.run(arguments = '--install-sandbox=%s' % destdir, stdout=expect)
diff --git a/test/Interactive/Alias.py b/test/Interactive/Alias.py
new file mode 100644
index 0000000..fc05b9a
--- /dev/null
+++ b/test/Interactive/Alias.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 the ability to build an Alias in --interactive mode.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+foo = Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Alias('foo-alias', foo)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo-alias\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+# Verify that "scons" can be used as a synonmyn for the "build" command.
+scons.send("scons foo-alias\n")
+
+scons.send("scons 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo-alias\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>> scons: `foo-alias' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/Default-None.py b/test/Interactive/Default-None.py
new file mode 100644
index 0000000..36ebf2f
--- /dev/null
+++ b/test/Interactive/Default-None.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 we get the expected error message when we use a "build"
+command without arguments and there are no default targets (because they
+explicitly called Default(None) in the SConstruct file).
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(combine=1)
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Default(None)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build\n")
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+# Verify that "scons" can be used as a synonmyn for the "build" command.
+scons.send("scons\n")
+
+scons.send("scons foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build\n")
+
+scons.send("build foo.out\n")
+
+expect_stdout = """\
+scons>>> scons: *** No targets specified and no Default() targets found. Stop.
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> scons: *** No targets specified and no Default() targets found. Stop.
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>> scons: *** No targets specified and no Default() targets found. Stop.
+scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/Default.py b/test/Interactive/Default.py
new file mode 100644
index 0000000..d6205e2
--- /dev/null
+++ b/test/Interactive/Default.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 that we can use a "build" command without arguments to (re-)build
+the Default() targets, without exiting the command loop.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+foo_out = Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Default(foo_out)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+# Verify that "scons" can be used as a synonmy for the "build" command.
+scons.send("scons\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/added-include.py b/test/Interactive/added-include.py
new file mode 100644
index 0000000..8c30314
--- /dev/null
+++ b/test/Interactive/added-include.py
@@ -0,0 +1,118 @@
+#!/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__"
+
+"""
+This verifies the --interactive command line option's ability to
+rebuild a target when an implicit dependency (include line) is
+added to the source file.
+"""
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('foo.h.in', """
+#define FOO_STRING "foo.h.in"
+""")
+
+test.write('foo.c', """
+#include <stdio.h>
+
+int main()
+{
+ printf("foo.c\\n");
+ return 0;
+}
+""")
+
+test.write('SConstruct', """
+env = Environment(CPPPATH=['.'])
+env.Command('foo.h', ['foo.h.in'], Copy('$TARGET', '$SOURCE'))
+env.Program('foo', ['foo.c'])
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+foo_exe = test.workpath('foo' + TestSCons._exe)
+_foo_exe_ = '"%s"' % string.replace(foo_exe, '\\', '\\\\')
+
+
+
+# Start scons, to build "foo"
+scons = test.start(arguments = '--interactive')
+
+scons.send("build %(_foo_exe_)s 1\n" % locals())
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.run(program = foo_exe, stdout = 'foo.c\n')
+
+
+
+
+# Update foo.c
+# We add a new #include line, to make sure that scons notices
+# the new implicit dependency and builds foo.h first.
+test.write('foo.c', """
+#include <foo.h>
+
+#include <stdio.h>
+
+int main()
+{
+ printf("%s\\n", FOO_STRING);
+ return 0;
+}
+""")
+
+scons.send("build %(_foo_exe_)s 2\n" % locals())
+
+test.wait_for(test.workpath('2'))
+
+# Run foo, and make sure it prints correctly
+test.run(program = foo_exe, stdout = 'foo.h.in\n')
+
+
+
+test.write('foo.h.in', """
+#define FOO_STRING "foo.h.in 3"
+""")
+
+
+
+scons.send("build %(_foo_exe_)s 3\n" % locals())
+
+test.wait_for(test.workpath('3'))
+
+# Run foo, and make sure it prints correctly
+test.run(program = foo_exe, stdout = 'foo.h.in 3\n')
+
+
+
+test.pass_test()
diff --git a/test/Interactive/basic.py b/test/Interactive/basic.py
new file mode 100644
index 0000000..4c78f69
--- /dev/null
+++ b/test/Interactive/basic.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 basic operation of the --interactive command line option to build
+a target, rebuild it when the input changes, and not rebuild it when
+the input doesn't change.
+
+Also tests that "scons" can be used as a synonym for "build".
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+# Verify that "scons" can be used as a synonmy for the "build" command.
+scons.send("scons foo.out 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo.out\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> Copy("foo.out", "foo.in")
+Touch("2")
+scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/cache-debug.py b/test/Interactive/cache-debug.py
new file mode 100644
index 0000000..dab5159
--- /dev/null
+++ b/test/Interactive/cache-debug.py
@@ -0,0 +1,117 @@
+#!/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 --interactive command line option to build a target when the
+--cache-debug option is used.
+"""
+
+import TestCmd
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+CacheDir('cache')
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+Command('4', [], Touch('$TARGET'))
+Command('5', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 4\n")
+
+test.wait_for(test.workpath('4'), popen=scons)
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build --cache-debug=- foo.out\n")
+
+scons.send("build 5\n")
+
+test.wait_for(test.workpath('5'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = \
+r"""scons>>> Copy\("foo.out", "foo.in"\)
+scons>>> Touch\("1"\)
+scons>>> Removed foo.out
+scons>>> Touch\("2"\)
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch\("3"\)
+scons>>> Removed foo.out
+scons>>> Touch\("4"\)
+scons>>> Retrieved `foo.out' from cache
+CacheRetrieve\(foo.out\): retrieving from [0-9A-za-z]+
+scons>>> Touch\("5"\)
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout, match=TestCmd.match_re)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/cache-disable.py b/test/Interactive/cache-disable.py
new file mode 100644
index 0000000..0fb8435
--- /dev/null
+++ b/test/Interactive/cache-disable.py
@@ -0,0 +1,115 @@
+#!/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 --interactive command line option to build
+a target when the --cache-disable option is used.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+CacheDir('cache')
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+Command('4', [], Touch('$TARGET'))
+Command('5', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 4\n")
+
+test.wait_for(test.workpath('4'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build --cache-disable foo.out\n")
+
+scons.send("build 5\n")
+
+test.wait_for(test.workpath('5'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Removed foo.out
+scons>>> Touch("2")
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch("3")
+scons>>> Removed foo.out
+scons>>> Touch("4")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("5")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/cache-force.py b/test/Interactive/cache-force.py
new file mode 100644
index 0000000..8fd3f92
--- /dev/null
+++ b/test/Interactive/cache-force.py
@@ -0,0 +1,113 @@
+#!/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 --interactive command line option to build a target when the
+--cache-force option is used.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+CacheDir('cache')
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+Command('4', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+import shutil
+shutil.rmtree(test.workpath('cache'))
+
+
+
+scons.send("build --cache-force foo.out\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build foo.out\n")
+
+scons.send("build 4\n")
+
+test.wait_for(test.workpath('4'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Removed foo.out
+scons>>> Touch("2")
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch("3")
+scons>>> scons: `foo.out' is up to date.
+scons>>> Removed foo.out
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch("4")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/cache-show.py b/test/Interactive/cache-show.py
new file mode 100644
index 0000000..c1fe487
--- /dev/null
+++ b/test/Interactive/cache-show.py
@@ -0,0 +1,115 @@
+#!/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 --interactive command line option to build a target when the
+--cache-show option is used.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+CacheDir('cache')
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+Command('4', [], Touch('$TARGET'))
+Command('5', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+scons.send("clean foo.out\n")
+
+scons.send("build 4\n")
+
+test.wait_for(test.workpath('4'))
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build --cache-show foo.out\n")
+
+scons.send("build 5\n")
+
+test.wait_for(test.workpath('5'))
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Removed foo.out
+scons>>> Touch("2")
+scons>>> Retrieved `foo.out' from cache
+scons>>> Touch("3")
+scons>>> Removed foo.out
+scons>>> Touch("4")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("5")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/clean.py b/test/Interactive/clean.py
new file mode 100644
index 0000000..4f4f80d
--- /dev/null
+++ b/test/Interactive/clean.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verifies operation of the --interactive command line option
+"clean" subcommand.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE'))
+Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE'))
+Command('f3.out', 'f3.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+test.write('f3.in', "f3.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build f1.out f2.out f3.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('f1.out'), "f1.in\n")
+test.must_match(test.workpath('f2.out'), "f2.in\n")
+test.must_match(test.workpath('f3.out'), "f3.in\n")
+
+
+
+scons.send("clean f1.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_not_exist('f1.out')
+test.must_exist('f2.out')
+test.must_exist('f3.out')
+
+
+
+scons.send("build -c\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_not_exist('f1.out')
+test.must_not_exist('f2.out')
+test.must_not_exist('f3.out')
+
+expect_stdout = """\
+scons>>> Copy("f1.out", "f1.in")
+Copy("f2.out", "f2.in")
+Copy("f3.out", "f3.in")
+scons>>> Touch("1")
+scons>>> Removed f1.out
+scons>>> Touch("2")
+scons>>> Removed 1
+Removed 2
+Removed f2.out
+Removed f3.out
+scons>>> Touch("3")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/exit.py b/test/Interactive/exit.py
new file mode 100644
index 0000000..df06d5d
--- /dev/null
+++ b/test/Interactive/exit.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 use of the "exit" subcommand.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+scons.send('exit\n')
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> """
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/help.py b/test/Interactive/help.py
new file mode 100644
index 0000000..ef4c578
--- /dev/null
+++ b/test/Interactive/help.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 the behavior of the "help" subcommand (and its "h" and "?" aliases).
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+scons.send('help\n')
+
+scons.send('h\n')
+
+scons.send('?\n')
+
+help_text = """\
+build [TARGETS] Build the specified TARGETS and their dependencies.
+ 'b' is a synonym.
+clean [TARGETS] Clean (remove) the specified TARGETS and their
+ dependencies. 'c' is a synonym.
+exit Exit SCons interactive mode.
+help [COMMAND] Prints help for the specified COMMAND. 'h' and
+ '?' are synonyms.
+shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and '!'
+ are synonyms.
+version Prints SCons version information.
+"""
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> %(help_text)s
+scons>>> %(help_text)s
+scons>>> %(help_text)s
+scons>>>
+""" % locals()
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/implicit-BuildDir.py b/test/Interactive/implicit-BuildDir.py
new file mode 100644
index 0000000..7b7aa4b
--- /dev/null
+++ b/test/Interactive/implicit-BuildDir.py
@@ -0,0 +1,142 @@
+#!/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__"
+
+"""
+This is a regression test for a bug in earlier versions of the
+--interactive command line option (specifically the original prototype
+submitted by Adam Simpkins, who created this test case).
+
+It tests to make sure that cached state is cleared between files for
+nodes in both the build tree and the source tree when BuildDirs are used.
+This is needed especially with BuildDirs created with duplicate=0, since
+the scanners scan the files in the source tree. Any cached implicit
+deps must be cleared on the source files.
+"""
+
+import os.path
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('src',
+ ['src', 'inc'])
+
+# Create the top-level SConstruct file
+test.write('SConstruct', """
+BUILD_ENV = Environment()
+Export('BUILD_ENV')
+
+hdr_dir = '#build/include'
+BUILD_ENV['HDR_DIR'] = hdr_dir
+BUILD_ENV.Append(CPPPATH = hdr_dir)
+
+BUILD_ENV.BuildDir('build', 'src', duplicate = 0)
+SConscript('build/SConscript')
+
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+# Create the src/SConscript file
+test.write(['src', 'SConscript'], """
+Import('BUILD_ENV')
+BUILD_ENV.Install(BUILD_ENV['HDR_DIR'], ['inc/foo.h'])
+BUILD_ENV.Program('foo', ['foo.c'])
+""")
+
+# Create src/foo.c
+test.write(['src', 'foo.c'], """
+#include <stdio.h>
+
+#define FOO_PRINT_STRING "Hello from foo.c"
+
+int main()
+{
+ printf(FOO_PRINT_STRING "\\n");
+ return 0;
+}
+""")
+
+# Create src/inc/foo.h
+test.write(['src', 'inc', 'foo.h'], """
+#ifndef INCLUDED_foo_h
+#define INCLUDED_foo_h
+
+#define FOO_PRINT_STRING "Hello from foo.h"
+
+#endif /* INCLUDED_foo_h */
+""")
+
+# Start scons, to build only "build/foo"
+build_foo_exe = os.path.join('build', 'foo' + TestSCons._exe)
+_build_foo_exe_ = '"%s"' % string.replace(build_foo_exe, '\\', '\\\\')
+abs_foo_exe = test.workpath(build_foo_exe)
+
+scons = test.start(arguments = '--interactive', combine=1)
+
+
+
+# Build build/foo
+scons.send('build %(_build_foo_exe_)s 1\n' % locals())
+
+test.wait_for(test.workpath('1'))
+
+# Run foo, and make sure it prints correctly
+test.run(program = abs_foo_exe, stdout = 'Hello from foo.c\n')
+
+
+
+# Update foo.c to include foo.h
+test.write(['src', 'foo.c'], """
+#include "foo.h"
+#include <stdio.h>
+
+int main()
+{
+ printf(FOO_PRINT_STRING "\\n");
+ return 0;
+}
+""")
+
+# Build build/foo
+scons.send('build %(_build_foo_exe_)s 2\n' % locals())
+
+test.wait_for(test.workpath('2'))
+
+# Run foo, and make sure it prints correctly
+test.run(program = abs_foo_exe, stdout = 'Hello from foo.h\n')
+
+
+
+scons.send('exit\n')
+
+test.finish(scons)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option--Q.py b/test/Interactive/option--Q.py
new file mode 100644
index 0000000..4c02fa7
--- /dev/null
+++ b/test/Interactive/option--Q.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 that use of the -Q option on an individual "build" command
+will suppress the progress messages.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '--interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("build -Q foo.out 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+expect_stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons>>> scons: Building targets ...
+Copy("foo.out", "foo.in")
+Touch("1")
+scons: done building targets.
+scons: Clearing cached node information ...
+scons: done clearing node information.
+scons>>> Copy("foo.out", "foo.in")
+Touch("2")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-i.py b/test/Interactive/option-i.py
new file mode 100644
index 0000000..a2935a7
--- /dev/null
+++ b/test/Interactive/option-i.py
@@ -0,0 +1,106 @@
+#!/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 -i option, specified on the build command, causes
+build errors to be ignored, just for that command.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+def error(target, source, env):
+ return 1
+e1 = Command('e1.out', 'e1.in', Action(error))
+e2 = Command('e2.out', 'e2.in', Action(error))
+f1 = Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE'))
+f2 = Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE'))
+Depends(f1, e1)
+Depends(f2, e2)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+test.write('e1.in', "e1.in\n")
+test.write('e2.in', "e2.in\n")
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive', combine=1)
+
+scons.send("build f1.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_not_exist(test.workpath('f1.out'))
+
+
+
+scons.send("build -i e1.out f1.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_match(test.workpath('f1.out'), "f1.in\n")
+
+
+
+scons.send("build f2.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'), popen=scons)
+
+test.must_not_exist(test.workpath('f2.out'))
+
+
+
+expect_stdout = """\
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+scons>>> Touch("1")
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+Copy("f1.out", "f1.in")
+scons>>> Touch("2")
+scons>>> error(["e2.out"], ["e2.in"])
+scons: *** [e2.out] Error 1
+scons>>> Touch("3")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-j.py b/test/Interactive/option-j.py
new file mode 100644
index 0000000..29bba88
--- /dev/null
+++ b/test/Interactive/option-j.py
@@ -0,0 +1,164 @@
+#!/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 "build" command of --interactive mode can take a -j
+option to build things in parallel.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(combine=1)
+
+test.write('SConstruct', """\
+import os
+import time
+from SCons.Script import *
+def cat(target, source, env):
+ t = str(target[0])
+ os.mkdir(t + '.started')
+ fp = open(t, 'wb')
+ for s in source:
+ fp.write(open(str(s), 'rb').read())
+ fp.close()
+ os.mkdir(t + '.finished')
+
+def must_be_finished(target, source, env, dir):
+ if not os.path.exists(dir):
+ msg = 'build failed, %s does not exist\\n' % dir
+ sys.stderr.write(msg)
+ return 1
+ return cat(target, source, env)
+
+def f1_a_out_must_be_finished(target, source, env):
+ return must_be_finished(target, source, env, 'f1-a.out.finished')
+def f3_a_out_must_be_finished(target, source, env):
+ return must_be_finished(target, source, env, 'f3-a.out.finished')
+
+def must_wait_for_f2_b_out(target, source, env):
+ t = str(target[0])
+ os.mkdir(t + '.started')
+ f2_b_started = 'f2-b.out.started'
+ while not os.path.exists(f2_b_started):
+ time.sleep(1)
+ fp = open(t, 'wb')
+ for s in source:
+ fp.write(open(str(s), 'rb').read())
+ fp.close()
+ os.mkdir(t + '.finished')
+
+def _f2_a_out_must_not_be_finished(target, source, env):
+ f2_a_started = 'f2-a.out.started'
+ f2_a_finished = 'f2-a.out.finished'
+ while not os.path.exists(f2_a_started):
+ time.sleep(1)
+ msg = 'f2_a_out_must_not_be_finished(["%s"], ["%s"])\\n' % (target[0], source[0])
+ sys.stdout.write(msg)
+ if os.path.exists(f2_a_finished):
+ msg = 'build failed, %s exists\\n' % f2_a_finished
+ sys.stderr.write(msg)
+ return 1
+ return cat(target, source, env)
+
+f2_a_out_must_not_be_finished = Action(_f2_a_out_must_not_be_finished,
+ strfunction = None)
+
+Cat = Action(cat)
+f1_a = Command('f1-a.out', 'f1-a.in', cat)
+f1_b = Command('f1-b.out', 'f1-b.in', f1_a_out_must_be_finished)
+f2_a = Command('f2-a.out', 'f2-a.in', must_wait_for_f2_b_out)
+f2_b = Command('f2-b.out', 'f2-b.in', f2_a_out_must_not_be_finished)
+f3_a = Command('f3-a.out', 'f3-a.in', cat)
+f3_b = Command('f3-b.out', 'f3-b.in', f3_a_out_must_be_finished)
+Command('f1.out', f1_a + f1_b, cat)
+Command('f2.out', f2_a + f2_b, cat)
+Command('f3.out', f3_a + f3_b, cat)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+test.write('f1-a.in', "f1-a.in\n")
+test.write('f1-b.in', "f1-b.in\n")
+test.write('f2-a.in', "f2-a.in\n")
+test.write('f2-b.in', "f2-b.in\n")
+test.write('f3-a.in', "f3-a.in\n")
+test.write('f3-b.in', "f3-b.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build f1.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_match(test.workpath('f1.out'), "f1-a.in\nf1-b.in\n")
+
+
+
+scons.send("build -j2 f2.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_match(test.workpath('f2.out'), "f2-a.in\nf2-b.in\n")
+
+
+
+scons.send("build f3.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'))
+
+test.must_match(test.workpath('f3.out'), "f3-a.in\nf3-b.in\n")
+
+
+
+expect_stdout = """\
+scons>>> cat(["f1-a.out"], ["f1-a.in"])
+f1_a_out_must_be_finished(["f1-b.out"], ["f1-b.in"])
+cat(["f1.out"], ["f1-a.out", "f1-b.out"])
+scons>>> Touch("1")
+scons>>> must_wait_for_f2_b_out(["f2-a.out"], ["f2-a.in"])
+f2_a_out_must_not_be_finished(["f2-b.out"], ["f2-b.in"])
+cat(["f2.out"], ["f2-a.out", "f2-b.out"])
+scons>>> Touch("2")
+scons>>> cat(["f3-a.out"], ["f3-a.in"])
+f3_a_out_must_be_finished(["f3-b.out"], ["f3-b.in"])
+cat(["f3.out"], ["f3-a.out", "f3-b.out"])
+scons>>> Touch("3")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-k.py b/test/Interactive/option-k.py
new file mode 100644
index 0000000..f15605e
--- /dev/null
+++ b/test/Interactive/option-k.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 that the -k option, specified on the build command, causes
+us to keep going and build additional targets.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+def error(target, source, env):
+ return 1
+e1 = Command('e1.out', 'e1.in', Action(error))
+f1 = Command('f1.out', 'f1.in', Copy('$TARGET', '$SOURCE'))
+Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE'))
+Command('f3.out', 'f3.in', Copy('$TARGET', '$SOURCE'))
+Depends(f1, e1)
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+Command('3', [], Touch('$TARGET'))
+""")
+
+test.write('e1.in', "e1.in\n")
+test.write('e2.in', "e2.in\n")
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive', combine=1)
+
+scons.send("build f1.out f2.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_not_exist(test.workpath('f1.out'))
+test.must_not_exist(test.workpath('f2.out'))
+
+
+
+scons.send("build -k f1.out f2.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_not_exist(test.workpath('f1.out'))
+test.must_match(test.workpath('f2.out'), "f2.in\n")
+
+
+
+scons.send("build f1.out f3.out\n")
+
+scons.send("build 3\n")
+
+test.wait_for(test.workpath('3'), popen=scons)
+
+test.must_not_exist(test.workpath('f1.out'))
+test.must_not_exist(test.workpath('f3.out'))
+
+
+
+expect_stdout = """\
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+scons>>> Touch("1")
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+Copy("f2.out", "f2.in")
+scons>>> Touch("2")
+scons>>> error(["e1.out"], ["e1.in"])
+scons: *** [e1.out] Error 1
+scons>>> Touch("3")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-n.py b/test/Interactive/option-n.py
new file mode 100644
index 0000000..f5ee1e3
--- /dev/null
+++ b/test/Interactive/option-n.py
@@ -0,0 +1,79 @@
+#!/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 -n option, specified on the build command, reports
+what would be built but doesn't actually build anything.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build -n foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'), popen=scons)
+
+test.must_not_exist(test.workpath('foo.out'))
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'), popen=scons)
+
+test.must_match(test.workpath('foo.out'), "foo.in\n")
+
+
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/option-s.py b/test/Interactive/option-s.py
new file mode 100644
index 0000000..167d581
--- /dev/null
+++ b/test/Interactive/option-s.py
@@ -0,0 +1,79 @@
+#!/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 --interactive command line option
+to build a target, rebuild it when the input changes, and not rebuild
+it when the input doesn't change.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("build -s foo.out 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo.out\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/repeat-line.py b/test/Interactive/repeat-line.py
new file mode 100644
index 0000000..e85b9ea
--- /dev/null
+++ b/test/Interactive/repeat-line.py
@@ -0,0 +1,87 @@
+#!/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 blank line repeats the last (build) command.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo.out\n")
+
+scons.send("\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> build foo.out 1
+Copy("foo.out", "foo.in")
+scons: `1' is up to date.
+scons>>> Touch("2")
+scons>>> scons: `foo.out' is up to date.
+scons>>> build foo.out
+scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/shell.py b/test/Interactive/shell.py
new file mode 100644
index 0000000..9d5e8a2
--- /dev/null
+++ b/test/Interactive/shell.py
@@ -0,0 +1,116 @@
+#!/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 of the "shell" command (and its "sh" and "!" aliases)
+to shell out of interactive mode.
+"""
+
+import string
+import sys
+
+import TestSCons
+
+test = TestSCons.TestSCons(combine=1)
+
+_python_ = TestSCons._python_
+
+shell_command_py = test.workpath('shell_command.py')
+_shell_command_py_ = '"%s"' % string.replace(shell_command_py, '\\', '\\\\')
+
+test.write(shell_command_py, """\
+print 'hello from shell_command.py'
+""")
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+scons.send('!%(_python_)s %(_shell_command_py_)s\n' % locals())
+
+scons.send("\n")
+
+scons.send('shell %(_python_)s %(_shell_command_py_)s\n' % locals())
+
+scons.send("\n")
+
+scons.send('sh %(_python_)s %(_shell_command_py_)s\n' % locals())
+
+scons.send("\n")
+
+scons.send('!no_such_command arg1 arg2\n')
+
+scons.send("\n")
+
+scons.send("build foo.out\n")
+
+scons.send("\n")
+
+if sys.platform == 'win32':
+ no_such_error = 'The system cannot find the file specified'
+else:
+ no_such_error = 'No such file or directory'
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> hello from shell_command.py
+scons>>> !%(_python_)s %(_shell_command_py_)s
+hello from shell_command.py
+scons>>> hello from shell_command.py
+scons>>> shell %(_python_)s %(_shell_command_py_)s
+hello from shell_command.py
+scons>>> hello from shell_command.py
+scons>>> sh %(_python_)s %(_shell_command_py_)s
+hello from shell_command.py
+scons>>> scons: no_such_command: %(no_such_error)s
+scons>>> !no_such_command arg1 arg2
+scons: no_such_command: %(no_such_error)s
+scons>>> scons: `foo.out' is up to date.
+scons>>> build foo.out
+scons: `foo.out' is up to date.
+scons>>>
+""" % locals()
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/taskmastertrace.py b/test/Interactive/taskmastertrace.py
new file mode 100644
index 0000000..23b9ad9
--- /dev/null
+++ b/test/Interactive/taskmastertrace.py
@@ -0,0 +1,90 @@
+#!/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 --taskmastertrace= option to the "build" command
+of --interactive mode.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("build --taskmastertrace=- foo.out\n")
+
+scons.send("build 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build foo.out\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> Taskmaster: 'foo.out': children:
+ ['foo.in']
+ waiting on unfinished children:
+ ['foo.in']
+Taskmaster: 'foo.in': evaluating foo.in
+Taskmaster: 'foo.out': children:
+ ['foo.in']
+ evaluating foo.out
+Copy("foo.out", "foo.in")
+scons>>> Touch("2")
+scons>>> scons: `foo.out' is up to date.
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/tree.py b/test/Interactive/tree.py
new file mode 100644
index 0000000..96e7d4a
--- /dev/null
+++ b/test/Interactive/tree.py
@@ -0,0 +1,91 @@
+#!/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 --interactive command line option to build
+a target, rebuild it when the input changes, and not rebuild it when
+the input doesn't change.
+
+Also tests that "scons" can be used as a synonym for "build".
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+Command('2', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out\n")
+
+scons.send("build 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+test.write('foo.in', "foo.in 2\n")
+
+scons.send("build --tree=all foo.out\n")
+
+scons.send("scons 2\n")
+
+test.wait_for(test.workpath('2'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 2\n")
+
+
+
+scons.send("build --debug=tree foo.out\n")
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+scons>>> Touch("1")
+scons>>> Copy("foo.out", "foo.in")
++-foo.out
+ +-foo.in
+scons>>> Touch("2")
+scons>>> scons: `foo.out' is up to date.
++-foo.out
+ +-foo.in
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/unknown-command.py b/test/Interactive/unknown-command.py
new file mode 100644
index 0000000..2b77378
--- /dev/null
+++ b/test/Interactive/unknown-command.py
@@ -0,0 +1,66 @@
+#!/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 message when an unknown command is typed in.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'))
+Command('1', [], Touch('$TARGET'))
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+
+
+scons = test.start(arguments = '-Q --interactive')
+
+scons.send("build foo.out 1\n")
+
+test.wait_for(test.workpath('1'))
+
+test.must_match(test.workpath('foo.out'), "foo.in 1\n")
+
+
+
+scons.send('this-is-an-unknown-command hello\n')
+
+expect_stdout = """\
+scons>>> Copy("foo.out", "foo.in")
+Touch("1")
+scons>>> *** Unknown command: this-is-an-unknown-command
+scons>>>
+"""
+
+test.finish(scons, stdout = expect_stdout)
+
+
+
+test.pass_test()
diff --git a/test/Interactive/version.py b/test/Interactive/version.py
new file mode 100644
index 0000000..84f70e8
--- /dev/null
+++ b/test/Interactive/version.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 behavior of the "version" subcommand.
+"""
+
+import TestCmd
+import TestSCons
+
+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, 2007'
+
+fmt = '(%s|Copyright \\(c\\) %s The SCons Foundation)\n'
+
+copyright_line = fmt % (copyright_marker, copyright_years)
+
+
+
+expect1 = """\
+scons>>>
+scons>>>
+"""
+
+expect2 = """\
+scons>>>
+scons>>>
+"""
+
+test.run(arguments = '-Q --interactive',
+ stdin = "version\nexit\n")
+
+# 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>>> SCons by Steven Knight et al\.:
+\tengine: v\S+, [^,]*, by \S+ on \S+
+%(copyright_line)sscons>>>
+""" % locals()
+
+expect2 = r"""scons>>> SCons by Steven Knight et al\.:
+\tscript: v\S+, [^,]*, by \S+ on \S+
+\tengine: v\S+, [^,]*, by \S+ on \S+
+%(copyright_line)sscons>>>
+""" % locals()
+
+stdout = test.stdout() + '\n'
+if not test.match_re(stdout, expect1) and not test.match_re(stdout, expect2):
+ print repr(stdout)
+ test.fail_test()
+
+
+
+test.pass_test()
diff --git a/test/Java/JAR.py b/test/Java/JAR.py
index f0951c6..ee552f4 100644
--- a/test/Java/JAR.py
+++ b/test/Java/JAR.py
@@ -120,21 +120,11 @@ test.run(arguments='classes.jar')
test.must_match('classes.jar',
'cvfm classes.jar foo.mf -C testdir bar.class\n')
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('jar', ENV=ENV):
- where_jar = test.detect('JAR', 'jar', ENV=ENV)
-else:
- where_jar = test.where_is('jar')
-if not where_jar:
- test.skip_test("Could not find Java jar, skipping test(s).\n")
+
+
+where_javac, java_version = test.java_where_javac()
+where_jar = test.java_where_jar()
+
test.write("wrapper.py", """\
diff --git a/test/Java/JARCHDIR.py b/test/Java/JARCHDIR.py
index f7d9fca..a3f2ec4 100644
--- a/test/Java/JARCHDIR.py
+++ b/test/Java/JARCHDIR.py
@@ -40,21 +40,8 @@ import TestSCons
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('jar', ENV=ENV):
- where_jar = test.detect('JAR', 'jar', ENV=ENV)
-else:
- where_jar = test.where_is('jar')
-if not where_jar:
- test.skip_test("Could not find Java jar, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_jar = test.java_where_jar()
diff --git a/test/Java/JARFLAGS.py b/test/Java/JARFLAGS.py
index 3939d98..03a222b 100644
--- a/test/Java/JARFLAGS.py
+++ b/test/Java/JARFLAGS.py
@@ -33,21 +33,10 @@ test = TestSCons.TestSCons()
test.subdir('src')
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('jar', ENV=ENV):
- where_jar = test.detect('JAR', 'jar', ENV=ENV)
-else:
- where_jar = test.where_is('jar')
-if not where_jar:
- test.skip_test("Could not find Java jar, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_jar = test.java_where_jar()
+
+
test.write('SConstruct', """
env = Environment(tools = ['javac', 'jar'],
@@ -75,9 +64,9 @@ public class Example1
expect = test.wrap_stdout("""\
%(where_javac)s -d classes -sourcepath src src/Example1\.java
-%(where_jar)s cvf test.jar classes/src/Example1\.class
+%(where_jar)s cvf test.jar -C classes src/Example1\.class
.*
-adding: classes/src/Example1\.class.*
+adding: src/Example1\.class.*
""" % locals())
expect = string.replace(expect, '/', os.sep)
diff --git a/test/Java/JAVABOOTCLASSPATH.py b/test/Java/JAVABOOTCLASSPATH.py
index 7723224..5962b94 100644
--- a/test/Java/JAVABOOTCLASSPATH.py
+++ b/test/Java/JAVABOOTCLASSPATH.py
@@ -38,21 +38,8 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
test.write('SConstruct', """
env = Environment(tools = ['javac', 'javah'],
diff --git a/test/Java/JAVACFLAGS.py b/test/Java/JAVACFLAGS.py
index 045fb7b..e287054 100644
--- a/test/Java/JAVACFLAGS.py
+++ b/test/Java/JAVACFLAGS.py
@@ -31,14 +31,7 @@ import TestSCons
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
test.subdir('src')
diff --git a/test/Java/JAVACLASSPATH.py b/test/Java/JAVACLASSPATH.py
index 0ae7dea..11f7c2c 100644
--- a/test/Java/JAVACLASSPATH.py
+++ b/test/Java/JAVACLASSPATH.py
@@ -36,21 +36,8 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
test.write('SConstruct', """
env = Environment(tools = ['javac', 'javah'],
diff --git a/test/Java/JAVAH.py b/test/Java/JAVAH.py
index ecd3737..95abd33 100644
--- a/test/Java/JAVAH.py
+++ b/test/Java/JAVAH.py
@@ -24,9 +24,9 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
+import os.path
import string
-import sys
+
import TestSCons
_python_ = TestSCons._python_
@@ -95,21 +95,11 @@ line 3
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
+if java_version:
+ java_version = repr(java_version)
@@ -125,6 +115,9 @@ test.write('SConstruct', """
foo = Environment(tools = ['javac', 'javah', 'install'],
JAVAC = r'%(where_javac)s',
JAVAH = r'%(where_javah)s')
+jv = %(java_version)s
+if jv:
+ foo['JAVAVERSION'] = jv
javah = foo.Dictionary('JAVAH')
bar = foo.Clone(JAVAH = r'%(_python_)s wrapper.py ' + javah)
foo.Java(target = 'class1', source = 'com/sub/foo')
diff --git a/test/Java/JAVASOURCEPATH.py b/test/Java/JAVASOURCEPATH.py
index 069e228..87e90ad 100644
--- a/test/Java/JAVASOURCEPATH.py
+++ b/test/Java/JAVASOURCEPATH.py
@@ -36,14 +36,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
test.write('SConstruct', """
env = Environment(tools = ['javac', 'javah'],
diff --git a/test/Java/Java-1.4.py b/test/Java/Java-1.4.py
index 3d3d47a..3c0e1ed 100644
--- a/test/Java/Java-1.4.py
+++ b/test/Java/Java-1.4.py
@@ -38,14 +38,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac('1.4')
@@ -234,10 +227,10 @@ public class NestedExample
{
public NestedExample()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
try {Thread.sleep(200);}
@@ -256,7 +249,7 @@ public class NestedExample
public static void main(String argv[])
{
- NestedExample e = new NestedExample();
+ new NestedExample();
}
}
""")
@@ -268,7 +261,7 @@ public class NestedExample
test.write(['src5', 'TestSCons.java'], """\
class TestSCons {
public static void main(String[] args) {
- Foo[] fooArray = new Foo[] { new Foo() };
+ new Foo();
}
}
@@ -355,12 +348,16 @@ def classes_must_match(dir, expect):
global failed
got = get_class_files(test.workpath(dir))
if expect != got:
- sys.stderr.write("Expected the following class files in '%s':\n" % dir)
- for c in expect:
- sys.stderr.write(' %s\n' % c)
- sys.stderr.write("Got the following class files in '%s':\n" % dir)
- for c in got:
- sys.stderr.write(' %s\n' % c)
+ missing = set(expect) - set(got)
+ if missing:
+ sys.stderr.write("Missing the following class files from '%s':\n" % dir)
+ for c in missing:
+ sys.stderr.write(' %s\n' % c)
+ unexpected = set(got) - set(expect)
+ if unexpected:
+ sys.stderr.write("Found the following unexpected class files in '%s':\n" % dir)
+ for c in unexpected:
+ sys.stderr.write(' %s\n' % c)
failed = 1
def classes_must_not_exist(dir, expect):
diff --git a/test/Java/Java-1.5.py b/test/Java/Java-1.5.py
index 4ac3d96..f6d93c7 100644
--- a/test/Java/Java-1.5.py
+++ b/test/Java/Java-1.5.py
@@ -38,15 +38,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-ENV['PATH'] = '/usr/lib/jvm/java-1.5.0-sun-1.5.0.11/bin' + os.pathsep + os.environ['PATH']
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac('1.5')
@@ -235,10 +227,10 @@ public class NestedExample
{
public NestedExample()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
try {Thread.sleep(200);}
@@ -257,7 +249,7 @@ public class NestedExample
public static void main(String argv[])
{
- NestedExample e = new NestedExample();
+ new NestedExample();
}
}
""")
diff --git a/test/Java/Java-1.6.py b/test/Java/Java-1.6.py
index f2b629a..5bd8e2f 100644
--- a/test/Java/Java-1.6.py
+++ b/test/Java/Java-1.6.py
@@ -38,15 +38,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-ENV['PATH'] = '/usr/lib/jvm/java-6-sun-1.6.0.00/bin' + os.pathsep + os.environ['PATH']
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac('1.6')
@@ -235,10 +227,10 @@ public class NestedExample
{
public NestedExample()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
- Thread t = new Thread() {
+ new Thread() {
public void start()
{
try {Thread.sleep(200);}
@@ -257,7 +249,7 @@ public class NestedExample
public static void main(String argv[])
{
- NestedExample e = new NestedExample();
+ new NestedExample();
}
}
""")
diff --git a/test/Java/RMIC.py b/test/Java/RMIC.py
index 2ab1804..f9721c2 100644
--- a/test/Java/RMIC.py
+++ b/test/Java/RMIC.py
@@ -92,21 +92,8 @@ line 3
test.fail_test(test.read(['outdir', 'test2.class']) != "test2.JAVA\nline 3\n")
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping non-simulated test(s).\n")
-
-if test.detect_tool('rmic', ENV=ENV):
- where_rmic = test.detect('RMIC', 'rmic', ENV=ENV)
-else:
- where_rmic = test.where_is('rmic')
-if not where_rmic:
- test.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_rmic = test.java_where_rmic()
test.write("wrapper.py", """\
import os
@@ -319,15 +306,20 @@ test.run(arguments = '.')
test.fail_test(test.read('wrapper.out') != "wrapper.py %s -d outdir2 -classpath class2 com.sub.bar.Example3 com.sub.bar.Example4\n" % where_rmic)
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Stub.class')))
-
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Stub.class')))
+test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Stub.class'))
+test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Stub.class'))
+test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Stub.class'))
+test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Stub.class'))
+
+# We used to check for _Skel.class files as well, but they're not
+# generated by default starting with Java 1.5, and they apparently
+# haven't been needed for a while. Don't bother looking, even if we're
+# running Java 1.4. If we think they're needed but they don't exist
+# the test.up_to_date() call below will detect it.
+#test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example1_Skel.class'))
+#test.must_exist(test.workpath('outdir1', 'com', 'sub', 'foo', 'Example2_Skel.class'))
+#test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example3_Skel.class'))
+#test.must_exist(test.workpath('outdir2', 'com', 'sub', 'bar', 'Example4_Skel.class'))
test.up_to_date(arguments = '.')
diff --git a/test/Java/RMICCOM.py b/test/Java/RMICCOM.py
index ed5e0d6..e8a5655 100644
--- a/test/Java/RMICCOM.py
+++ b/test/Java/RMICCOM.py
@@ -40,9 +40,9 @@ test.subdir('src')
-out_file1 = os.path.join('out', 'file1', 'class_Skel.class')
-out_file2 = os.path.join('out', 'file2', 'class_Skel.class')
-out_file3 = os.path.join('out', 'file3', 'class_Skel.class')
+out_file1 = os.path.join('out', 'file1', 'class_Stub.class')
+out_file2 = os.path.join('out', 'file2', 'class_Stub.class')
+out_file3 = os.path.join('out', 'file3', 'class_Stub.class')
diff --git a/test/Java/RMICCOMSTR.py b/test/Java/RMICCOMSTR.py
index 5a451eb..a92bac5 100644
--- a/test/Java/RMICCOMSTR.py
+++ b/test/Java/RMICCOMSTR.py
@@ -41,9 +41,9 @@ test.subdir('src')
-out_file1 = os.path.join('out', 'file1', 'class_Skel.class')
-out_file2 = os.path.join('out', 'file2', 'class_Skel.class')
-out_file3 = os.path.join('out', 'file3', 'class_Skel.class')
+out_file1 = os.path.join('out', 'file1', 'class_Stub.class')
+out_file2 = os.path.join('out', 'file2', 'class_Stub.class')
+out_file3 = os.path.join('out', 'file3', 'class_Stub.class')
diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py
index d185b4d..9cac759 100644
--- a/test/Java/multi-step.py
+++ b/test/Java/multi-step.py
@@ -33,22 +33,8 @@ import TestSCons
test = TestSCons.TestSCons()
-# This test requires javac and swig
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
swig = test.where_is('swig')
if not swig:
diff --git a/test/Java/no-JARCHDIR.py b/test/Java/no-JARCHDIR.py
new file mode 100644
index 0000000..795689c
--- /dev/null
+++ b/test/Java/no-JARCHDIR.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 the Jar() behavior when we have no JARCHDIR set (it should
+automatically use the classdir that was deduced from the Java() call)
+and when we explicity set it to None (it should not use the Java()
+classdir attribute at all).
+"""
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+where_javac, java_version = test.java_where_javac()
+where_jar = test.java_where_jar()
+
+test.subdir('src')
+
+
+
+test.write(['src', 'a.java'], """\
+package foo.bar;
+public class a {}
+""")
+
+test.write(['src', 'b.java'], """\
+package foo.bar;
+public class b {}
+""")
+
+
+
+test.write('SConstruct', """\
+env = Environment(tools = ['javac', 'jar'],
+ JAVAC = r'%(where_javac)s',
+ JAR = r'%(where_jar)s')
+
+jar = env.Jar('x.jar', env.Java(target = 'classes', source = 'src'))
+""" % locals())
+
+test.run(arguments = '.')
+
+
+
+test.run(program = where_jar, arguments = 'tf x.jar')
+
+expect = """\
+foo/bar/a.class
+foo/bar/b.class
+"""
+
+if string.find(test.stdout(), expect) == -1:
+ print "Did not find expected string in standard output."
+ print "Expected =========================================================="
+ print expect
+ print "Output ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+
+
+test.run(arguments = '-c')
+
+
+
+test.write('SConstruct', """\
+env = Environment(tools = ['javac', 'jar'],
+ JAVAC = r'%(where_javac)s',
+ JAR = r'%(where_jar)s',
+ JARCHDIR = None)
+
+jar = env.Jar('x.jar', env.Java(target = 'classes', source = 'src'))
+""" % locals())
+
+test.run(arguments = '.')
+
+
+
+test.run(program = where_jar, arguments = 'tf x.jar')
+
+expect = """\
+classes/foo/bar/a.class
+classes/foo/bar/b.class
+"""
+
+if string.find(test.stdout(), expect) == -1:
+ print "Did not find expected string in standard output."
+ print "Expected =========================================================="
+ print expect
+ print "Output ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+
+
+test.pass_test()
diff --git a/test/Java/source-files.py b/test/Java/source-files.py
index 8d2506f..63d1d92 100644
--- a/test/Java/source-files.py
+++ b/test/Java/source-files.py
@@ -35,14 +35,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
test.write('SConstruct', """
diff --git a/test/Java/swig-dependencies.py b/test/Java/swig-dependencies.py
index 8df5e09..5477a2d 100644
--- a/test/Java/swig-dependencies.py
+++ b/test/Java/swig-dependencies.py
@@ -34,29 +34,14 @@ import TestSCons
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
-
-if test.detect_tool('jar', ENV=ENV):
- where_jar = test.detect('JAR', 'jar', ENV=ENV)
-else:
- where_jar = test.where_is('jar')
-if not where_jar:
- test.skip_test("Could not find Java jar, skipping test(s).\n")
+swig = test.where_is('swig')
+if not swig:
+ test.skip_test('Can not find installed "swig", skipping test.\n')
+
+where_javac, java_version = test.java_where_javac()
+where_javah = test.java_where_javah()
+where_jar = test.java_where_jar()
test.subdir(['foo'],
['java'],
diff --git a/test/LIBPATH.py b/test/Libs/LIBPATH.py
index 7fd4f9b..7fd4f9b 100644
--- a/test/LIBPATH.py
+++ b/test/Libs/LIBPATH.py
diff --git a/test/LIBPREFIX.py b/test/Libs/LIBPREFIX.py
index a71e967..a71e967 100644
--- a/test/LIBPREFIX.py
+++ b/test/Libs/LIBPREFIX.py
diff --git a/test/LIBPREFIXES.py b/test/Libs/LIBPREFIXES.py
index 1e5d6c2..1e5d6c2 100644
--- a/test/LIBPREFIXES.py
+++ b/test/Libs/LIBPREFIXES.py
diff --git a/test/LIBS.py b/test/Libs/LIBS.py
index e9f6545..e9f6545 100644
--- a/test/LIBS.py
+++ b/test/Libs/LIBS.py
diff --git a/test/LIBSUFFIX.py b/test/Libs/LIBSUFFIX.py
index a71e967..a71e967 100644
--- a/test/LIBSUFFIX.py
+++ b/test/Libs/LIBSUFFIX.py
diff --git a/test/LIBSUFFIXES.py b/test/Libs/LIBSUFFIXES.py
index 29cbb18..29cbb18 100644
--- a/test/LIBSUFFIXES.py
+++ b/test/Libs/LIBSUFFIXES.py
diff --git a/test/Library.py b/test/Libs/Library.py
index 4bcb2c7..4bcb2c7 100644
--- a/test/Library.py
+++ b/test/Libs/Library.py
diff --git a/test/SHLIBPREFIX.py b/test/Libs/SHLIBPREFIX.py
index 87b92fa..87b92fa 100644
--- a/test/SHLIBPREFIX.py
+++ b/test/Libs/SHLIBPREFIX.py
diff --git a/test/SHLIBSUFFIX.py b/test/Libs/SHLIBSUFFIX.py
index dc88e3b..dc88e3b 100644
--- a/test/SHLIBSUFFIX.py
+++ b/test/Libs/SHLIBSUFFIX.py
diff --git a/test/SharedLibrary.py b/test/Libs/SharedLibrary.py
index f8447ca..f8447ca 100644
--- a/test/SharedLibrary.py
+++ b/test/Libs/SharedLibrary.py
diff --git a/test/Libs/SharedLibraryIxes.py b/test/Libs/SharedLibraryIxes.py
new file mode 100644
index 0000000..f9d1471
--- /dev/null
+++ b/test/Libs/SharedLibraryIxes.py
@@ -0,0 +1,261 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test that we can build shared libraries and link against shared
+libraries that have non-standard library prefixes and suffixes.
+"""
+
+import re
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import sys
+isWindows = sys.platform == 'win32'
+
+env = Environment()
+
+# Make sure that the shared library can be located at runtime.
+env.Append(RPATH=['.'])
+env.Append(LIBPATH=['.'])
+
+# We first bake the LIBSUFFIXES, so that it will not change as a
+# side-effect of changing SHLIBSUFFIX.
+env['LIBSUFFIXES'] = map( env.subst, env.get('LIBSUFFIXES', []))
+
+weird_prefixes = ['libXX', 'libYY']
+
+if isWindows:
+ weird_suffixes = ['.xxx', '.yyy', '.xxx.dll', '.yyy.dll']
+ env.Append(CCFLAGS = '/MD')
+elif env['PLATFORM'] == 'darwin':
+ weird_suffixes = ['.xxx.dylib', '.yyy.dylib']
+else:
+ weird_suffixes = ['.xxx.so', '.yyy.so']
+
+shlibprefix = env.subst('$SHLIBPREFIX')
+shlibsuffix = env.subst('$SHLIBSUFFIX')
+
+progprefix = env.subst('$PROGPREFIX')
+progsuffix = env.subst('$PROGSUFFIX')
+
+goo_obj = env.SharedObject(source='goo.c')
+foo_obj = env.SharedObject(source='foo.c')
+prog_obj = env.SharedObject(source='prog.c')
+
+#
+# The following functions define all the different way that one can
+# use link againt a shared library.
+#
+def nodeInSrc(source, lib, libname):
+ return (source+lib, '')
+
+def pathInSrc(source, lib, libname):
+ return (source+map(str,lib), '')
+
+def nodeInLib(source, lib, libname):
+ return (source, lib)
+
+def pathInLib(source, lib, libname):
+ return (source, map(str,lib))
+
+def nameInLib(source, lib, libname):
+ # NOTE: libname must contain both the proper prefix and suffix.
+ #
+ # When using non-standard prefixes and suffixes, one has to
+ # provide the full name of the library since scons can not know
+ # which of the non-standard extension to use.
+ #
+ # Note that this is not necessarally SHLIBPREFIX and
+ # SHLIBSUFFIX. These are the ixes of the target library, not the
+ # ixes of the library that we are linking againt.
+ return (source, libname)
+
+libmethods = [
+ nodeInSrc, pathInSrc, nodeInLib, pathInLib,
+ nameInLib ]
+
+def buildAndlinkAgainst(builder, target, source, method, lib, libname, **kw):
+ '''Build a target using a given builder while linking againt a given
+ library using a specified method for linking against the library.'''
+
+ # On Windows, we have to link against the .lib file.
+ if isWindows:
+ for l in lib:
+ if str(l)[-4:] == '.lib':
+ lib = [l]
+ break
+ (source, LIBS) = method(source, lib, libname)
+ #build = builder(target=target, source=source, LIBS=LIBS, **kw)
+ kw = kw.copy()
+ kw['target'] = target
+ kw['source'] = source
+ kw['LIBS'] = LIBS
+ build = apply(builder, (), kw)
+
+ # Check that the build target depends on at least one of the
+ # library target.
+ found_dep = False
+ children = build[0].children()
+ for l in lib:
+ if l in children:
+ found_dep = True
+ break;
+ assert found_dep, \
+ "One of %s not found in %s, method=%s, libname=%s, shlibsuffix=%s" % \
+ (map(str,lib), map(str, build[0].children()), method.__name__, libname, shlibsuffix)
+ return build
+
+def prog(i,
+ goomethod, goolibprefix, goolibsuffix,
+ foomethod, foolibprefix, foolibsuffix):
+ '''Build a program
+
+ The program links against a shared library foo which itself links
+ against a shared library goo. The libraries foo and goo can use
+ arbitrary library prefixes and suffixes.'''
+
+ goo_name = goolibprefix+'goo'+str(i)+goolibsuffix
+ foo_name = foolibprefix+'foo'+str(i)+foolibsuffix
+ prog_name = progprefix+'prog'+str(i)+progsuffix
+
+ print 'Prog: %d, %s, %s, %s' % (i, goo_name, foo_name, prog_name)
+
+ # On Windows, we have to link against the .lib file.
+ if isWindows:
+ goo_libname = goolibprefix+'goo'+str(i)+'.lib'
+ foo_libname = foolibprefix+'foo'+str(i)+'.lib'
+ else:
+ goo_libname = goo_name
+ foo_libname = foo_name
+
+ goo_lib = env.SharedLibrary(
+ goo_name, goo_obj, SHLIBSUFFIX=goolibsuffix)
+ foo_lib = buildAndlinkAgainst(
+ env.SharedLibrary, foo_name, foo_obj,
+ goomethod, goo_lib, goo_libname, SHLIBSUFFIX=foolibsuffix)
+ prog = buildAndlinkAgainst(env.Program, prog_name, prog_obj,
+ foomethod, foo_lib, foo_libname)
+
+
+#
+# Create the list of all possible permutations to test.
+#
+i = 0
+tests = []
+prefixes = [shlibprefix] + weird_prefixes
+suffixes = [shlibsuffix] + weird_suffixes
+for foolibprefix in prefixes:
+ for foolibsuffix in suffixes:
+ for foomethod in libmethods:
+ for goolibprefix in prefixes:
+ for goolibsuffix in suffixes:
+ for goomethod in libmethods:
+ tests.append(
+ (i,
+ goomethod, goolibprefix, goolibsuffix,
+ foomethod, foolibprefix, foolibsuffix))
+ i = i + 1
+
+#
+# Pseudo-randomly choose 200 tests to run out of the possible
+# tests. (Testing every possible permutation would take too long.)
+#
+import random
+random.seed(123456)
+try:
+ random.shuffle(tests)
+except AttributeError:
+ pass
+
+for i in range(200):
+ apply(prog, tests[i])
+
+""")
+
+test.write('goo.c', r"""
+#include <stdio.h>
+
+#ifdef _WIN32
+#define EXPORT __declspec( dllexport )
+#else
+#define EXPORT
+#endif
+
+EXPORT void
+goo(void)
+{
+ printf("goo.c\n");
+}
+""")
+
+test.write('foo.c', r"""
+#include <stdio.h>
+
+#ifdef _WIN32
+#define EXPORT __declspec( dllexport )
+#else
+#define EXPORT
+#endif
+
+EXPORT void
+foo(void)
+{
+ goo();
+ printf("foo.c\n");
+}
+""")
+
+test.write('prog.c', r"""
+#include <stdio.h>
+
+void foo(void);
+int
+main(int argc, char *argv[])
+{
+ argv[argc++] = "--";
+ foo();
+ printf("prog.c\n");
+ return 0;
+}
+""")
+
+test.run(arguments = '.',
+ stderr=TestSCons.noisy_ar,
+ match=TestSCons.match_re_dotall)
+
+tests = re.findall(r'Prog: (\d+), (\S+), (\S+), (\S+)', test.stdout())
+expected = "goo.c\nfoo.c\nprog.c\n"
+
+for t in tests:
+ test.must_exist(t[1])
+ test.must_exist(t[2])
+ test.must_exist(t[3])
+ test.run(program = test.workpath(t[3]), stdout=expected)
+
+test.pass_test()
diff --git a/test/LoadableModule.py b/test/LoadableModule.py
index 5243fbf..4a8e1ed 100644
--- a/test/LoadableModule.py
+++ b/test/LoadableModule.py
@@ -105,7 +105,8 @@ test.run(arguments = '.',
if string.find(sys.platform, 'darwin') != -1:
test.run(program='/usr/bin/file',
arguments = "foo1",
- stdout="foo1: Mach-O bundle ppc\n")
+ match = TestCmd.match_re,
+ stdout="foo1: Mach-O bundle (ppc|i386)\n")
if sys.platform in platforms_with_dlopen:
os.environ['LD_LIBRARY_PATH'] = test.workpath()
diff --git a/test/MSVC/pdb-manifest.py b/test/MSVC/pdb-manifest.py
new file mode 100644
index 0000000..00f3ee2
--- /dev/null
+++ b/test/MSVC/pdb-manifest.py
@@ -0,0 +1,81 @@
+#!/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 .pdb files work correctly in conjunction with manifest files.
+"""
+
+import sys
+
+import TestSCons
+
+_exe = TestSCons._exe
+_dll = TestSCons._dll
+_lib = TestSCons._lib
+
+test = TestSCons.TestSCons()
+
+if sys.platform != 'win32':
+ msg = "Skipping Visual C/C++ test on non-Windows platform '%s'\n" % sys.platform
+ test.skip_test(msg)
+
+test.write('SConstruct', """\
+env = Environment()
+
+env['WINDOWS_INSERT_DEF'] = True
+env['WINDOWS_INSERT_MANIFEST'] = True
+env['PDB'] = '${TARGET.base}.pdb'
+env.Program('test', 'test.cpp')
+env.SharedLibrary('sharedlib', 'test.cpp')
+env.StaticLibrary('staticlib', 'test.cpp')
+""")
+
+test.write('test.cpp', """\
+#include <stdio.h>
+#include <stdlib.h>
+int
+main(int argc, char *argv)
+{
+ printf("test.cpp\\n");
+ exit (0);
+}
+""")
+
+test.write('sharedlib.def', """\
+""")
+
+test.run(arguments = '.')
+
+test.must_exist('test%s' % _exe)
+test.must_exist('test.pdb')
+
+test.must_exist('sharedlib%s' % _dll)
+test.must_exist('sharedlib.pdb')
+
+test.must_exist('staticlib%s' % _lib)
+test.must_not_exist('staticlib.pdb')
+
+test.pass_test()
diff --git a/test/QT/moc-from-header.py b/test/QT/moc-from-header.py
index 2878136..9936490 100644
--- a/test/QT/moc-from-header.py
+++ b/test/QT/moc-from-header.py
@@ -55,6 +55,8 @@ test.Qt_create_SConstruct('SConstruct')
test.write('SConscript', """\
Import("env")
env.Program(target = 'aaa', source = 'aaa.cpp')
+if env['PLATFORM'] == 'darwin':
+ env.Install('.', 'qt/lib/libmyqt.dylib')
""")
test.write('aaa.cpp', r"""
@@ -67,7 +69,7 @@ test.write('aaa.h', r"""
void aaa(void) Q_OBJECT;
""")
-test.run(arguments = aaa_exe)
+test.run()
test.up_to_date(options = '-n', arguments=aaa_exe)
diff --git a/test/QT/warnings.py b/test/QT/warnings.py
index baa1e6f..ef94dd6 100644
--- a/test/QT/warnings.py
+++ b/test/QT/warnings.py
@@ -59,9 +59,10 @@ match12 = r"""
scons: warning: Generated moc file 'aaa.moc' is not included by 'aaa.cpp'
""" + TestSCons.file_expr
-# In case 'ar' gives a warning about creating a library.
-test.fail_test(not test.match_re(test.stderr(), match12) and \
- not test.match_re(test.stderr(), match12 + ".+\n"))
+if not re.search(match12, test.stderr()):
+ print "Did not find expected regular expression in stderr:"
+ print test.stderr()
+ test.fail_test()
os.environ['QTDIR'] = test.QT
diff --git a/test/Repository/Java.py b/test/Repository/Java.py
index 6e8bbd6..67ef605 100644
--- a/test/Repository/Java.py
+++ b/test/Repository/Java.py
@@ -37,18 +37,8 @@ python = TestSCons.python
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-where_java = test.where_is('java')
-if not where_java:
- test.skip_test("Could not find Java java, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_java = test.java_where_java()
java = where_java
@@ -115,6 +105,8 @@ test.writable('repository', 0)
#
test.run(chdir = 'work1', options = opts, arguments = ".")
+os.environ['JAVA_HOME'] = '/usr/lib/jvm/java-1.5.0-sun-1.5.0.11'
+
test.run(program = java,
arguments = "-cp %s Foo1" % work1_classes,
stdout = "rep1/src/Foo1.java\n")
diff --git a/test/Repository/JavaH.py b/test/Repository/JavaH.py
index fc87904..258d9bd 100644
--- a/test/Repository/JavaH.py
+++ b/test/Repository/JavaH.py
@@ -37,25 +37,9 @@ python = TestSCons.python
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('javah', ENV=ENV):
- where_javah = test.detect('JAVAH', 'javah', ENV=ENV)
-else:
- where_javah = test.where_is('javah')
-if not where_javah:
- test.skip_test("Could not find Java javah, skipping test(s).\n")
-
-where_java = test.where_is('java')
-if not where_java:
- test.skip_test("Could not find Java java, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_java = test.java_where_java()
+where_javah = test.java_where_javah()
java = where_java
javac = where_javac
diff --git a/test/Repository/LIBPATH.py b/test/Repository/LIBPATH.py
index 9216a8b..0f80ace 100644
--- a/test/Repository/LIBPATH.py
+++ b/test/Repository/LIBPATH.py
@@ -59,6 +59,13 @@ def write_LIBDIRFLAGS(env, target, source):
return 0
env_zzz.Command('zzz.out', aaa_exe, write_LIBDIRFLAGS)
env_yyy.Command('yyy.out', bbb_exe, write_LIBDIRFLAGS)
+
+if env_yyy['PLATFORM'] == 'darwin':
+ # The Mac OS X linker complains about nonexistent directories
+ # specified as -L arguments. Suppress its warnings so we don't
+ # treat the warnings on stderr as a failure.
+ env_yyy.Append(LINKFLAGS=['-w'])
+ env_zzz.Append(LINKFLAGS=['-w'])
""")
test.write(['work', 'aaa.c'], r"""
diff --git a/test/Repository/RMIC.py b/test/Repository/RMIC.py
index ebe6a83..bf8edff 100644
--- a/test/Repository/RMIC.py
+++ b/test/Repository/RMIC.py
@@ -28,34 +28,17 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test building Java applications when using Repositories.
"""
-import os
import string
-import sys
+
import TestSCons
python = TestSCons.python
test = TestSCons.TestSCons()
-ENV = test.java_ENV()
-
-if test.detect_tool('javac', ENV=ENV):
- where_javac = test.detect('JAVAC', 'javac', ENV=ENV)
-else:
- where_javac = test.where_is('javac')
-if not where_javac:
- test.skip_test("Could not find Java javac, skipping test(s).\n")
-
-if test.detect_tool('rmic', ENV=ENV):
- where_rmic = test.detect('RMIC', 'rmic', ENV=ENV)
-else:
- where_rmic = test.where_is('rmic')
-if not where_rmic:
- test.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n")
-
-where_java = test.where_is('java')
-if not where_java:
- test.skip_test("Could not find Java java, skipping test(s).\n")
+where_javac, java_version = test.java_where_javac()
+where_java = test.java_where_java()
+where_rmic = test.java_where_rmic()
java = where_java
javac = where_javac
@@ -185,15 +168,20 @@ test.run(chdir = 'work1', options = opts, arguments = ".")
# see that they were built from the proper rep1 sources, but I don't
# know how to do that with RMI, so punt for now.
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
+
+# We used to check for _Skel.class files as well, but they're not
+# generated by default starting with Java 1.5, and they apparently
+# haven't been needed for a while. Don't bother looking, even if we're
+# running Java 1.4. If we think they're needed but they don't exist
+# the variou test.up_to_date() calls below will detect it.
+#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
+#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
test.up_to_date(chdir = 'work1', options = opts, arguments = ".")
@@ -294,15 +282,15 @@ test.fail_test(string.find(test.stdout(), ' com.sub.foo.Foo1 com.sub.foo.Foo2')
# see that they were built from the proper work1 sources, but I don't
# know how to do that with RMI, so punt for now.
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
+test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_not_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
+#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_exist (test.workpath('work1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
test.up_to_date(chdir = 'work1', options = opts, arguments = ".")
@@ -315,10 +303,11 @@ test.run(chdir = 'rep1', options = opts, arguments = ".")
# see that they were built from the proper work1 sources, but I don't
# know how to do that with RMI, so punt for now.
-test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
+
+#test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_exist(test.workpath('rep1', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
test.up_to_date(chdir = 'rep1', options = opts, arguments = ".")
@@ -343,13 +332,16 @@ Local(rmi_classes)
test.run(chdir = 'work3', options = opts, arguments = ".")
-test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Hello.class')))
-test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo1.class')))
-test.fail_test(os.path.exists(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo2.class')))
+test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Hello.class'))
+test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo1.class'))
+test.must_not_exist(test.workpath('work3', 'classes', 'com', 'sub', 'foo', 'Foo2.class'))
+
+test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class'))
+test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class'))
+
+#test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class'))
+#test.must_exist (test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class'))
-test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo1_Stub.class')))
-test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Skel.class')))
-test.fail_test(not os.path.exists(test.workpath('work3', 'outdir', 'com', 'sub', 'foo', 'Foo2_Stub.class')))
+test.up_to_date(chdir = 'work3', options = opts, arguments = ".")
test.pass_test()
diff --git a/test/SWIG/module-parens.py b/test/SWIG/module-parens.py
new file mode 100644
index 0000000..0d89ebe
--- /dev/null
+++ b/test/SWIG/module-parens.py
@@ -0,0 +1,102 @@
+#!/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 handle %module(directors="1") statements, both with and
+without white space before the opening parenthesis.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+swig = test.where_is('swig')
+
+if not swig:
+ test.skip_test('Can not find installed "swig", skipping test.\n')
+
+python_include_dir = test.get_python_inc()
+
+test.write(['SConstruct'], """\
+env = Environment(SWIGFLAGS = '-python',
+ CPPPATH=r"%(python_include_dir)s")
+
+import sys
+if sys.version[0] == '1':
+ # SWIG requires the -classic flag on pre-2.0 Python versions.
+ env.Append(SWIGFLAGS = ' -classic')
+
+env.SharedLibrary('test1.so', 'test1.i')
+env.SharedLibrary('test2.so', 'test2.i')
+""" % locals())
+
+test.write(['test1.cc'], """\
+int test1func()
+{
+ return 0;
+}
+""")
+
+test.write(['test1.h'], """\
+int test1func();
+""")
+
+test.write(['test1.i'], """\
+%module(directors="1") test1
+
+%{
+#include "test1.h"
+%}
+
+%include "test1.h"
+""")
+
+test.write(['test2.cc'], """\
+int test2func()
+{
+ return 0;
+}
+""")
+
+test.write(['test2.h'], """\
+int test2func();
+""")
+
+test.write(['test2.i'], """\
+%module (directors="1") test2
+
+%{
+#include "test2.h"
+%}
+
+%include "test2.h"
+""")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py
index dd2c938..ef91189 100644
--- a/test/Scanner/generated.py
+++ b/test/Scanner/generated.py
@@ -318,10 +318,10 @@ def write_out(file, dict):
f.write(file + ": " + str(dict[k]) + "\\n")
f.close()
-orig_function = CScan.scan
+orig_function = CScan.__call__
-def MyCScan(node, paths, orig_function=orig_function):
- deps = orig_function(node, paths)
+def MyCScan(node, paths, cwd, orig_function=orig_function):
+ deps = orig_function(node, paths, cwd)
global Scanned
n = str(node)
@@ -333,7 +333,7 @@ def MyCScan(node, paths, orig_function=orig_function):
return deps
-CScan.scan = MyCScan
+CScan.__call__ = MyCScan
env = Environment(CPPPATH = ".")
l = env.StaticLibrary("g", Split("libg_1.c libg_2.c libg_3.c"))
diff --git a/test/TEX/build_dir_dup0.py b/test/TEX/build_dir_dup0.py
new file mode 100644
index 0000000..8035957
--- /dev/null
+++ b/test/TEX/build_dir_dup0.py
@@ -0,0 +1,257 @@
+#!/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()
+
+latex = test.where_is('latex')
+dvipdf = test.where_is('dvipdf')
+makeindex = test.where_is('makeindex')
+bibtex = test.where_is('bibtex')
+if not latex or not makeindex or not bibtex or not dvipdf:
+ test.skip_test("Could not find 'latex', 'makeindex', 'bibtex', or dvipdf; skipping test.\n")
+
+test.subdir(['docs'])
+
+
+test.write(['SConstruct'], """\
+import os
+
+env = Environment(ENV = { 'PATH' : os.environ['PATH'] },
+ TOOLS = ['tex', 'latex', 'dvipdf'])
+Export(['env'])
+
+SConscript(os.path.join('docs', 'SConscript'),
+ build_dir=os.path.join('mybuild','docs'),
+ duplicate=0)
+""")
+
+
+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
+%%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/
+
+%% Saved with string encoding Western (ASCII)
+
+@techreport{AnAuthor:2006fk,
+ Author = {A. N. Author},
+ 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{AnAuthor: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/multi-run.py b/test/TEX/multi-run.py
index d4e2d79..686263d 100644
--- a/test/TEX/multi-run.py
+++ b/test/TEX/multi-run.py
@@ -28,6 +28,8 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Validate that both .tex and .ltx files can handle a LaTeX-style
bibliography (by calling $BIBTEX to generate a .bbl file) and
correctly re-run to resolve undefined references.
+
+Also verifies that package warnings are caught and re-run as needed.
"""
import string
@@ -42,7 +44,7 @@ latex = test.where_is('latex')
if not tex and not latex:
test.skip_test("Could not find tex or latex; skipping test(s).\n")
-test.subdir('work1', 'work2', 'work4')
+test.subdir('work1', 'work2', 'work3', 'work4')
input_file = r"""
@@ -64,6 +66,62 @@ Hello world.
\end{document}
"""
+input_file3 = r"""
+\documentclass{article}
+\usepackage{longtable}
+
+\begin{document}
+As stated in the last paper, this is a bug-a-boo.
+here is some more junk and another table
+here is some more junk and another table
+
+\begin{longtable}[l]{rlll}
+ Isotope &\multicolumn{1}{c}{Abar} &Name\\
+\\
+ 1001 &1.0078 &Proton &$p$\\
+ 1002 &2.0141 &Deuterium &$d$\\
+ 1003 &3.0170 &Tritium &$t$\\
+ 2003 &3.0160 &Helium 3 &He$^3$\\
+ 2004 &4.0026 &Helium 4 &He$^{4}$\\
+\end{longtable}
+
+and a closing comment
+
+ These parameters and arrays are filled in when the parameter \textbf{iftnrates}
+ is set to 1:
+
+\begin{longtable}[l]{ll}
+\\
+\textbf{nxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{pxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{nxxxxx} &Total number of particles made by xxxxx reaction\\
+\textbf{nxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{pxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{nxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{pxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{nxxxxx} &Total number of particles made by xxxxx reaction\\
+\textbf{nxxxx} &Total number of particles made by xxxx reaction\\
+\textbf{pxxxx} &Total number of particles made by xxxx reaction\\
+\\
+\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rnxxxxx} &Regional total of particles made by xxxxx reaction\\
+\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rnxxxxx} &Regional total of particles made by xxxxx reaction\\
+\textbf{rnxxxx} &Regional total of particles made by xxxx reaction\\
+\textbf{rpxxxx} &Regional total of particles made by xxxx reaction\\
+\\
+\textbf{reactot}(r) &Total number of reactions for reaction r\\
+\textbf{reacreg}(r,ir) &Total number of reactions for reaction r in region ir\\
+\end{longtable}
+
+
+\end{document}
+"""
+
bibfile = r"""
@Article{X,
author = "Mr. X",
@@ -95,6 +153,20 @@ PDF( "foo.tex" )
print foo_log
test.fail_test(1)
+ test.write(['work3', 'SConstruct'], """\
+DVI( "foo3.tex" )
+""")
+
+ test.write(['work3', 'foo3.tex'], input_file3)
+
+ test.run(chdir = 'work3', arguments = '.')
+
+ foo_log = test.read(['work3', 'foo3.log'])
+ if string.find(foo_log, 'Rerun LaTeX') != -1:
+ print 'foo.log contains "Rerun LaTeX":'
+ print foo_log
+ test.fail_test(1)
+
if latex:
@@ -117,6 +189,20 @@ PDF( "foo.ltx" )
print foo_log
test.fail_test(1)
+ test.write(['work3', 'SConstruct'], """\
+DVI( "foo3.tex" )
+PDF( "foo3.tex" )
+""")
+
+ test.write(['work3', 'foo3.tex'], input_file3)
+
+ test.run(chdir = 'work3', arguments = '.')
+
+ foo_log = test.read(['work3', 'foo3.log'])
+ if string.find(foo_log, 'Rerun LaTeX') != -1:
+ print 'foo.log contains "Rerun LaTeX":'
+ print foo_log
+ test.fail_test(1)
test.write(['work4', 'SConstruct'], """\
diff --git a/test/YACC/live.py b/test/YACC/live.py
index 4934570..0e5f156 100644
--- a/test/YACC/live.py
+++ b/test/YACC/live.py
@@ -103,13 +103,19 @@ graph: GRAPH_T
%%
""")
+import sys
+if sys.platform == 'darwin':
+ file_hpp = 'file.cpp.h'
+else:
+ file_hpp = 'file.hpp'
+
test.write("hello.cpp", """\
-#include "file.hpp"
+#include "%(file_hpp)s"
int main()
{
}
-""")
+""" % locals())
test.write('foo.y', yacc % 'foo.y')
diff --git a/test/build-errors.py b/test/build-errors.py
deleted file mode 100644
index e25fbd5..0000000
--- a/test/build-errors.py
+++ /dev/null
@@ -1,223 +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
-import string
-import sys
-import TestCmd
-import TestSCons
-
-test = TestSCons.TestSCons()
-
-no_such_file = test.workpath("no_such_file")
-not_executable = test.workpath("not_executable")
-
-test.write(not_executable, "\n")
-
-test.write("f1.in", "\n")
-test.write("f2.in", "\n")
-test.write("f3.in", "\n")
-
-test.write('SConstruct1', r"""
-bld = Builder(action = '%s $SOURCES $TARGET')
-env = Environment(BUILDERS = { 'bld' : bld })
-env.bld(target = 'f1', source = 'f1.in')
-""" % string.replace(no_such_file, '\\', '\\\\'))
-
-test.run(arguments='-f SConstruct1 .',
- stdout = test.wrap_stdout("%s f1.in f1\n" % no_such_file, error=1),
- stderr = None,
- status = 2)
-
-bad_command = """\
-Bad command or file name
-"""
-
-unrecognized = """\
-'%s' is not recognized as an internal or external command,
-operable program or batch file.
-scons: *** [%s] Error 1
-"""
-
-unspecified = """\
-The name specified is not recognized as an
-internal or external command, operable program or batch file.
-scons: *** [%s] Error 1
-"""
-
-not_found_1 = """
-sh: %s: not found
-scons: *** [%s] Error 1
-"""
-
-not_found_2 = """
-sh: %s: not found
-scons: *** [%s] Error 1
-"""
-
-No_such = """\
-%s: No such file or directory
-scons: *** [%s] Error 127
-"""
-
-cannot_execute = """\
-%s: cannot execute
-scons *** [%s] Error 126
-"""
-
-Permission_denied = """\
-%s: Permission denied
-scons: *** [%s] Error 126
-"""
-
-permission_denied = """\
-%s: permission denied
-scons: *** [%s] Error 126
-"""
-
-is_a_directory = """\
-%s: is a directory
-scons: *** [%s] Error 126
-"""
-
-test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
-if os.name == 'nt':
- errs = [
- bad_command,
- unrecognized % (no_such_file, 'f1'),
- unspecified % 'f1'
- ]
- test.fail_test(not test.stderr() in errs)
-else:
- errs = [
- not_found_1 % (no_such_file, 'f1'),
- not_found_2 % (no_such_file, 'f1'),
- No_such % (no_such_file, 'f1'),
- ]
- error_message_not_found = 1
- for err in errs:
- if string.find(test.stderr(), err) != -1:
- error_message_not_found = None
- break
- test.fail_test(error_message_not_found)
-
-test.write('SConstruct2', r"""
-bld = Builder(action = '%s $SOURCES $TARGET')
-env = Environment(BUILDERS = { 'bld': bld })
-env.bld(target = 'f2', source = 'f2.in')
-""" % string.replace(not_executable, '\\', '\\\\'))
-
-test.run(arguments='-f SConstruct2 .',
- stdout = test.wrap_stdout("%s f2.in f2\n" % not_executable, error=1),
- stderr = None,
- status = 2)
-
-test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
-if os.name == 'nt':
- errs = [
- bad_command,
- unrecognized % (not_executable, 'f2'),
- unspecified % 'f2'
- ]
- test.fail_test(not test.stderr() in errs)
-else:
- errs = [
- cannot_execute % (not_executable, 'f2'),
- Permission_denied % (not_executable, 'f2'),
- permission_denied % (not_executable, 'f2'),
- ]
- error_message_not_found = 1
- for err in errs:
- if string.find(test.stderr(), err) != -1:
- error_message_not_found = None
- break
- test.fail_test(error_message_not_found)
-
-test.write('SConstruct3', r"""
-bld = Builder(action = '%s $SOURCES $TARGET')
-env = Environment(BUILDERS = { 'bld' : bld })
-env.bld(target = 'f3', source = 'f3.in')
-""" % string.replace(test.workdir, '\\', '\\\\'))
-
-test.run(arguments='-f SConstruct3 .',
- stdout = test.wrap_stdout("%s f3.in f3\n" % test.workdir, error=1),
- stderr = None,
- status = 2)
-
-test.description_set("Incorrect STDERR:\n%s\n" % test.stderr())
-if os.name == 'nt':
- errs = [
- bad_command,
- unrecognized % (test.workdir, 'f3'),
- unspecified % 'f3'
- ]
- test.fail_test(not test.stderr() in errs)
-else:
- errs = [
- cannot_execute % (not_executable, 'f3'),
- is_a_directory % (test.workdir, 'f3'),
- ]
- error_message_not_found = 1
- for err in errs:
- if string.find(test.stderr(), err) != -1:
- error_message_not_found = None
- break
- test.fail_test(error_message_not_found)
-
-test.write('SConstruct4', r"""
-env = Environment()
-env.Command('test.out', 'test.in', Copy('$TARGET', '$SOURCE'))
-env.InstallAs('test2.out', 'test.out')
-# Mark test2.out as precious so we'll handle the exception in
-# FunctionAction() rather than when the target is cleaned before building.
-env.Precious('test2.out')
-env.Default('test2.out')
-""")
-
-test.write('test.in', "test.in 1\n")
-
-test.run(arguments = '-f SConstruct4 .')
-
-test.write('test.in', "test.in 2\n")
-
-test.writable('test2.out', 0)
-f = open(test.workpath('test2.out'))
-
-test.run(arguments = '-f SConstruct4 .',
- stderr = None,
- status = 2)
-
-f.close()
-test.writable('test2.out', 1)
-
-test.description_set("Incorrect STDERR:\n%s" % test.stderr())
-errs = [
- "scons: *** [test2.out] test2.out: Permission denied\n",
- "scons: *** [test2.out] test2.out: permission denied\n",
-]
-test.fail_test(test.stderr() not in errs)
-
-test.pass_test()
diff --git a/test/builderrors.py b/test/builderrors.py
index 8c7c4ab..28c9a0a 100644
--- a/test/builderrors.py
+++ b/test/builderrors.py
@@ -145,10 +145,10 @@ test.fail_test(string.find(err, 'Exception') != -1 or \
# Test bad shell ('./one' is a dir, so it can't be used as a shell).
# This will also give an exit status not in exitvalmap,
-# with error "Permission denied".
+# with error "Permission denied" or "No such file or directory".
test.write('SConstruct', """
env=Environment()
-if env['PLATFORM'] == 'posix':
+if env['PLATFORM'] in ('posix', 'darwin'):
from SCons.Platform.posix import fork_spawn
env['SPAWN'] = fork_spawn
env['SHELL'] = 'one'
@@ -157,10 +157,14 @@ env.Command(target='badshell.out', source=[], action='foo')
test.run(status=2, stderr=None)
err = test.stderr()
-test.fail_test(string.find(err, 'Exception') != -1 or \
- string.find(err, 'Traceback') != -1)
-test.fail_test(string.find(err, "ermission") == -1 and \
- string.find(err, "such file") == -1)
+if string.find(err, 'Exception') != -1 or string.find(err, 'Traceback') != -1:
+ print "Exception or Traceback found in the following error output:"
+ print err
+ test.fail_test()
+if string.find(err, 'ermission') == -1 and string.find(err, 'such file') == -1:
+ print "Missing '[Pp]ermission' or 'such file' string in the following error output:"
+ print err
+ test.fail_test()
# Test command with exit status -1.
diff --git a/test/import.py b/test/import.py
index 9c5d3af..85948f9 100644
--- a/test/import.py
+++ b/test/import.py
@@ -96,6 +96,7 @@ tools = [
'g77',
'gas',
'gcc',
+ 'gfortran',
'gnulink',
'gs',
'hpc++',
diff --git a/test/option-k.py b/test/option-k.py
index 0a46606..4a460a2 100644
--- a/test/option-k.py
+++ b/test/option-k.py
@@ -32,7 +32,7 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
-test.subdir('work1', 'work2')
+test.subdir('work1', 'work2', 'work3')
@@ -49,6 +49,11 @@ import sys
sys.exit(1)
""")
+
+#
+# Test: work1
+#
+
test.write(['work1', 'SConstruct'], """\
Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS')
Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS')
@@ -90,7 +95,27 @@ test.must_not_exist(test.workpath('work1', 'aaa.1'))
test.must_not_exist(test.workpath('work1', 'aaa.out'))
test.must_match(['work1', 'bbb.out'], "succeed.py: bbb.out\n")
+expect = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Cleaning targets ...
+Removed bbb.out
+scons: done cleaning targets.
+"""
+
+test.run(chdir = 'work1',
+ arguments = '--clean --keep-going aaa.out bbb.out',
+ stdout = expect)
+
+test.must_not_exist(test.workpath('work1', 'aaa.1'))
+test.must_not_exist(test.workpath('work1', 'aaa.out'))
+test.must_not_exist(test.workpath('work1', 'bbb.out'))
+
+
+#
+# Test: work2
+#
test.write(['work2', 'SConstruct'], """\
Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS')
@@ -126,4 +151,145 @@ test.must_match(['work2', 'ddd.out'], "succeed.py: ddd.out\n")
+#
+# Test: work3
+#
+# Check that the -k (keep-going) switch works correctly when the Nodes
+# forms a DAG. The test case is the following
+#
+# all
+# |
+# +-----+-----+-------------+
+# | | |
+# a1 a2 a3
+# | | |
+# + +---+---+ +---+---+
+# \ | / | |
+# \ bbb.out / a4 ccc.out
+# \ / /
+# \ / /
+# \ / /
+# aaa.out (fails)
+#
+
+test.write(['work3', 'SConstruct'], """\
+Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS')
+Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS')
+env = Environment(BUILDERS = { 'Succeed' : Succeed, 'Fail' : Fail })
+a = env.Fail('aaa.out', 'aaa.in')
+b = env.Succeed('bbb.out', 'bbb.in')
+c = env.Succeed('ccc.out', 'ccc.in')
+
+a1 = Alias( 'a1', a )
+a2 = Alias( 'a2', a+b)
+a4 = Alias( 'a4', c)
+a3 = Alias( 'a3', a4+c)
+
+Alias('all', a1+a2+a3)
+""" % locals())
+
+test.write(['work3', 'aaa.in'], "aaa.in\n")
+test.write(['work3', 'bbb.in'], "bbb.in\n")
+test.write(['work3', 'ccc.in'], "ccc.in\n")
+
+
+# Test tegular build (i.e. without -k)
+test.run(chdir = 'work3',
+ arguments = '.',
+ status = 2,
+ stderr = None,
+ stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+%(_python_)s ../fail.py aaa.out
+scons: building terminated because of errors.
+""" % locals())
+
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_not_exist(['work3', 'bbb.out'])
+test.must_not_exist(['work3', 'ccc.out'])
+
+
+test.run(chdir = 'work3',
+ arguments = '-c .')
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_not_exist(['work3', 'bbb.out'])
+test.must_not_exist(['work3', 'ccc.out'])
+
+
+# Current directory
+test.run(chdir = 'work3',
+ arguments = '-k .',
+ status = 2,
+ stderr = None,
+ stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+%(_python_)s ../fail.py aaa.out
+%(_python_)s ../succeed.py bbb.out
+%(_python_)s ../succeed.py ccc.out
+scons: done building targets (errors occurred during build).
+""" % locals())
+
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_exist(['work3', 'bbb.out'])
+test.must_exist(['work3', 'ccc.out'])
+
+
+test.run(chdir = 'work3',
+ arguments = '-c .')
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_not_exist(['work3', 'bbb.out'])
+test.must_not_exist(['work3', 'ccc.out'])
+
+
+# Single target
+test.run(chdir = 'work3',
+ arguments = '--keep-going all',
+ status = 2,
+ stderr = None,
+ stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+%(_python_)s ../fail.py aaa.out
+%(_python_)s ../succeed.py bbb.out
+%(_python_)s ../succeed.py ccc.out
+scons: done building targets (errors occurred during build).
+""" % locals())
+
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_exist(['work3', 'bbb.out'])
+test.must_exist(['work3', 'ccc.out'])
+
+
+test.run(chdir = 'work3',
+ arguments = '-c .')
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_not_exist(['work3', 'bbb.out'])
+test.must_not_exist(['work3', 'ccc.out'])
+
+
+# Separate top-level targets
+test.run(chdir = 'work3',
+ arguments = '-k a1 a2 a3',
+ status = 2,
+ stderr = None,
+ stdout = """\
+scons: Reading SConscript files ...
+scons: done reading SConscript files.
+scons: Building targets ...
+%(_python_)s ../fail.py aaa.out
+%(_python_)s ../succeed.py bbb.out
+%(_python_)s ../succeed.py ccc.out
+scons: done building targets (errors occurred during build).
+""" % locals())
+
+test.must_not_exist(['work3', 'aaa.out'])
+test.must_exist(['work3', 'bbb.out'])
+test.must_exist(['work3', 'ccc.out'])
+
+
test.pass_test()
diff --git a/test/option/debug-includes.py b/test/option/debug-includes.py
index 172cbb0..70857e6 100644
--- a/test/option/debug-includes.py
+++ b/test/option/debug-includes.py
@@ -79,7 +79,14 @@ includes = """
+-bar.h
"""
test.run(arguments = "--debug=includes foo.ooo")
-test.fail_test(string.find(test.stdout(), includes) == -1)
+
+if string.find(test.stdout(), includes) == -1:
+ print "Did not find expected string in standard output."
+ print "Expected =========================================================="
+ print includes
+ print "Actual ============================================================"
+ print test.stdout()
+ test.fail_test()
# In an ideal world, --debug=includes would also work when there's a build
# failure, but this would require even more complicated logic to scan
diff --git a/test/option/debug-memoizer.py b/test/option/debug-memoizer.py
index 8c8b2cf..ad35b5d 100644
--- a/test/option/debug-memoizer.py
+++ b/test/option/debug-memoizer.py
@@ -29,6 +29,7 @@ Test calling the --debug=memoizer option.
"""
import os
+import new
import string
import TestSCons
@@ -39,15 +40,22 @@ test = TestSCons.TestSCons(match = TestSCons.match_re)
class M:
def __init__(cls, name, bases, cls_dict):
- cls.has_metaclass = 1
-
-class A:
- __metaclass__ = M
+ cls.use_metaclass = 1
+ def fake_method(self):
+ pass
+ new.instancemethod(fake_method, None, cls)
try:
- has_metaclass = A.has_metaclass
+ class A:
+ __metaclass__ = M
+
+ use_metaclass = A.use_metaclass
except AttributeError:
- has_metaclass = None
+ use_metaclass = None
+ reason = 'no metaclasses'
+except TypeError:
+ use_metaclass = None
+ reason = 'new.instancemethod\\(\\) bug'
@@ -72,12 +80,8 @@ expect = [
"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:
+if use_metaclass:
def run_and_check(test, args, desc):
test.run(arguments = args)
@@ -92,6 +96,12 @@ if has_metaclass:
else:
+ expect_no_metaclasses = """
+scons: warning: memoization is not supported in this version of Python \\(%s\\)
+""" % reason
+
+ expect_no_metaclasses = expect_no_metaclasses + TestSCons.file_expr
+
def run_and_check(test, args, desc):
test.run(arguments = args, stderr = expect_no_metaclasses)
stdout = test.stdout()
diff --git a/test/option/stack-size.py b/test/option/stack-size.py
new file mode 100644
index 0000000..495f86d
--- /dev/null
+++ b/test/option/stack-size.py
@@ -0,0 +1,357 @@
+#!/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
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+isStackSizeAvailable = False
+try:
+ import threading
+ isStackSizeAvailable = hasattr(threading,'stack_size')
+except ImportError:
+ pass
+
+test.subdir('work1', 'work2')
+
+test.write('build.py', r"""
+import sys
+contents = open(sys.argv[2], 'rb').read()
+file = open(sys.argv[1], 'wb')
+file.write(contents)
+file.close()
+""")
+
+
+test.write(['work1', 'SConstruct'], """
+B = Builder(action = r'%(_python_)s ../build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS = { 'B' : B })
+f1 = env.B(target = 'f1.out', source = 'f1.in')
+f2 = env.B(target = 'f2.out', source = 'f2.in')
+Requires(f2, f1)
+""" % locals())
+
+test.write(['work1', 'f1.in'], "f1.in\n")
+test.write(['work1', 'f2.in'], "f2.in\n")
+
+
+test.write(['work2', 'SConstruct'], """
+SetOption('stack_size', 128)
+B = Builder(action = r'%(_python_)s ../build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS = { 'B' : B })
+f1 = env.B(target = 'f1.out', source = 'f1.in')
+f2 = env.B(target = 'f2.out', source = 'f2.in')
+Requires(f2, f1)
+""" % locals())
+
+test.write(['work2', 'f1.in'], "f1.in\n")
+test.write(['work2', 'f2.in'], "f2.in\n")
+
+
+
+expected_stdout = test.wrap_stdout("""\
+%(_python_)s ../build.py f1.out f1.in
+%(_python_)s ../build.py f2.out f2.in
+""" % locals())
+
+re_expected_stdout = string.replace(expected_stdout, '\\', '\\\\')
+
+expect_unsupported = """
+scons: warning: Setting stack size is unsupported by this version of Python:
+ (('module' object|'threading' module) has no attribute 'stack_size'|stack_size)
+File .*
+"""
+
+
+#
+# Test without any options
+#
+test.run(chdir='work1',
+ arguments = '.',
+ stdout=expected_stdout,
+ stderr='')
+test.must_exist(['work1', 'f1.out'])
+test.must_exist(['work1', 'f2.out'])
+
+test.run(chdir='work1',
+ arguments = '-c .')
+test.must_not_exist(['work1', 'f1.out'])
+test.must_not_exist(['work1', 'f2.out'])
+
+#
+# Test with -j2
+#
+test.run(chdir='work1',
+ arguments = '-j2 .',
+ stdout=expected_stdout,
+ stderr='')
+test.must_exist(['work1', 'f1.out'])
+test.must_exist(['work1', 'f2.out'])
+
+test.run(chdir='work1',
+ arguments = '-j2 -c .')
+test.must_not_exist(['work1', 'f1.out'])
+test.must_not_exist(['work1', 'f2.out'])
+
+
+#
+# Test with --stack-size
+#
+test.run(chdir='work1',
+ arguments = '--stack-size=128 .',
+ stdout=expected_stdout,
+ stderr='')
+test.must_exist(['work1', 'f1.out'])
+test.must_exist(['work1', 'f2.out'])
+
+test.run(chdir='work1',
+ arguments = '--stack-size=128 -c .')
+test.must_not_exist(['work1', 'f1.out'])
+test.must_not_exist(['work1', 'f2.out'])
+
+#
+# Test with SetOption('stack_size', 128)
+#
+test.run(chdir='work2',
+ arguments = '.',
+ stdout=expected_stdout,
+ stderr='')
+test.must_exist(['work2', 'f1.out'])
+test.must_exist(['work2', 'f2.out'])
+
+test.run(chdir='work2',
+ arguments = '--stack-size=128 -c .')
+test.must_not_exist(['work2', 'f1.out'])
+test.must_not_exist(['work2', 'f2.out'])
+
+if isStackSizeAvailable:
+ #
+ # Test with -j2 --stack-size=128
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=16
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 .',
+ match=TestSCons.match_re,
+ stdout=re_expected_stdout,
+ stderr="""
+scons: warning: Setting stack size failed:
+ size not valid: 16384 bytes
+File .*
+""")
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 -c .',
+ match=TestSCons.match_re,
+ stderr="""
+scons: warning: Setting stack size failed:
+ size not valid: 16384 bytes
+File .*
+""")
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 SetOption('stack_size', 128)
+ #
+ test.run(chdir='work2',
+ arguments = '-j2 .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work2', 'f1.out'])
+ test.must_exist(['work2', 'f2.out'])
+
+ test.run(chdir='work2',
+ arguments = '-j2 -c .')
+ test.must_not_exist(['work2', 'f1.out'])
+ test.must_not_exist(['work2', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=128 --warn=no-stack-size
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 --warn=no-stack-size -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=16 --warn=no-stack-size
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 --warn=no-stack-size -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --warn=no-stack-size SetOption('stack_size', 128)
+ #
+ test.run(chdir='work2',
+ arguments = '-j2 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work2', 'f1.out'])
+ test.must_exist(['work2', 'f2.out'])
+
+ test.run(chdir='work2',
+ arguments = '-j2 --warn=no-stack-size -c .')
+ test.must_not_exist(['work2', 'f1.out'])
+ test.must_not_exist(['work2', 'f2.out'])
+
+else:
+
+ #
+ # Test with -j2 --stack-size=128
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 .',
+ match=TestSCons.match_re,
+ stdout=re_expected_stdout,
+ stderr=expect_unsupported)
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 -c .',
+ match=TestSCons.match_re,
+ stderr=expect_unsupported)
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=16
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 .',
+ match=TestSCons.match_re,
+ stdout=re_expected_stdout,
+ stderr=expect_unsupported)
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 -c .',
+ match=TestSCons.match_re,
+ stderr=expect_unsupported)
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 SetOption('stack_size', 128)
+ #
+ test.run(chdir='work2',
+ arguments = '-j2 .',
+ match=TestSCons.match_re,
+ stdout=re_expected_stdout,
+ stderr=expect_unsupported)
+ test.must_exist(['work2', 'f1.out'])
+ test.must_exist(['work2', 'f2.out'])
+
+ test.run(chdir='work2',
+ arguments = '-j2 -c .',
+ match=TestSCons.match_re,
+ stderr=expect_unsupported)
+ test.must_not_exist(['work2', 'f1.out'])
+ test.must_not_exist(['work2', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=128 --warn=no-stack-size
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=128 --warn=no-stack-size -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --stack-size=16 --warn=no-stack-size
+ #
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work1', 'f1.out'])
+ test.must_exist(['work1', 'f2.out'])
+
+ test.run(chdir='work1',
+ arguments = '-j2 --stack-size=16 --warn=no-stack-size -c .')
+ test.must_not_exist(['work1', 'f1.out'])
+ test.must_not_exist(['work1', 'f2.out'])
+
+ #
+ # Test with -j2 --warn=no-stack-size SetOption('stack_size', 128)
+ #
+ test.run(chdir='work2',
+ arguments = '-j2 --warn=no-stack-size .',
+ stdout=expected_stdout,
+ stderr='')
+ test.must_exist(['work2', 'f1.out'])
+ test.must_exist(['work2', 'f2.out'])
+
+ test.run(chdir='work2',
+ arguments = '-j2 --warn=no-stack-size -c .')
+ test.must_not_exist(['work2', 'f1.out'])
+ test.must_not_exist(['work2', 'f2.out'])
+
+test.pass_test()
diff --git a/test/scons-time/func/file.py b/test/scons-time/func/file.py
index c9486c4..079c125 100644
--- a/test/scons-time/func/file.py
+++ b/test/scons-time/func/file.py
@@ -31,7 +31,7 @@ affect how the func subcommand processes things.
import TestSCons_time
-test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re)
+test = TestSCons_time.TestSCons_time()
try:
import pstats
@@ -56,22 +56,43 @@ prefix = 'foo-001'
expect1 = r'\d.\d\d\d prof1\.py:1\(_main\)' + '\n'
-test.run(arguments = 'func -f st1.conf', stdout = expect1)
+test.run(arguments = 'func -f st1.conf',
+ match = TestSCons_time.match_re,
+ stdout = expect1)
test.write('st2.conf', """\
prefix = 'foo'
title = 'ST2.CONF TITLE'
+vertical_bars = (
+ ( 1.4, 7, None ),
+ ( 1.5, 7, "label 1.5" ),
+ ( 1.6, 7, "label 1.6" ),
+)
""")
expect2 = \
r"""set title "ST2.CONF TITLE"
set key bottom left
-plot '-' title "Startup" with lines lt 1
+set label 3 "label 1.5" at 0.5,1.5 right
+set label 4 "label 1.6" at 0.6,1.5 right
+plot '-' title "Startup" with lines lt 1, \
+ '-' notitle with lines lt 7, \
+ '-' title "label 1.5" with lines lt 7, \
+ '-' title "label 1.6" with lines lt 7
# Startup
1 0.000
2 0.000
e
+1.4 0
+1.4 1
+e
+1.5 0
+1.5 1
+e
+1.6 0
+1.6 1
+e
"""
test.run(arguments = 'func --file st2.conf --fmt gnuplot', stdout = expect2)
diff --git a/test/scons-time/mem/file.py b/test/scons-time/mem/file.py
index a236df7..a1e7181 100644
--- a/test/scons-time/mem/file.py
+++ b/test/scons-time/mem/file.py
@@ -53,16 +53,23 @@ test.run(arguments = 'mem -f st1.conf', stdout = expect1)
test.write('st2.conf', """\
prefix = 'foo'
title = 'ST2.CONF TITLE'
+vertical_bars = (
+ ( 1.5, 7, None ),
+)
""")
expect2 = \
r"""set title "ST2.CONF TITLE"
set key bottom left
-plot '-' title "Startup" with lines lt 1
+plot '-' title "Startup" with lines lt 1, \
+ '-' notitle with lines lt 7
# Startup
1 4000.000
2 4000.000
e
+1.5 0
+1.5 4800
+e
"""
test.run(arguments = 'mem --file st2.conf --fmt gnuplot', stdout = expect2)
diff --git a/test/scons-time/obj/file.py b/test/scons-time/obj/file.py
index c881397..3cf8e74 100644
--- a/test/scons-time/obj/file.py
+++ b/test/scons-time/obj/file.py
@@ -53,16 +53,23 @@ test.run(arguments = 'obj -f st1.conf Node.FS.Base', stdout = expect1)
test.write('st2.conf', """\
prefix = 'foo'
title = 'ST2.CONF TITLE'
+vertical_bars = (
+ ( 1.5, 7, None ),
+)
""")
expect2 = \
r"""set title "ST2.CONF TITLE"
set key bottom left
-plot '-' title "Startup" with lines lt 1
+plot '-' title "Startup" with lines lt 1, \
+ '-' notitle with lines lt 7
# Startup
1 16040.000
2 16040.000
e
+1.5 0
+1.5 18000
+e
"""
test.run(arguments = 'obj --file st2.conf --fmt gnuplot Node.FS.Base', stdout = expect2)
diff --git a/test/scons-time/run/aegis.py b/test/scons-time/run/aegis.py
index 8f378cb..641f129 100644
--- a/test/scons-time/run/aegis.py
+++ b/test/scons-time/run/aegis.py
@@ -59,22 +59,9 @@ test.must_exist('foo-329-0.log',
'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'),
+ test.tempdir_re('src', 'script', 'scons.py'),
+ 'SCONS_LIB_DIR = %s' % test.tempdir_re('src', 'engine'),
]
content = test.read(test.workpath('foo-321-2.log'))
diff --git a/test/scons-time/run/config/archive_list.py b/test/scons-time/run/config/archive_list.py
index 8d48d26..8ddde3d 100644
--- a/test/scons-time/run/config/archive_list.py
+++ b/test/scons-time/run/config/archive_list.py
@@ -38,9 +38,11 @@ test.write_fake_scons_py()
test.write_sample_project('foo.tar.gz')
test.write('config', """\
-archive_list = ['foo.tar.gz']
+archive_list = ['foo.tar.gz', 'foo-file']
""")
+test.write('foo-file', "foo-file\n")
+
test.run(arguments = 'run -f config')
test.must_exist('foo-000-0.log',
@@ -50,6 +52,8 @@ test.must_exist('foo-000-0.log',
'foo-000-2.log',
'foo-000-2.prof')
+test.must_exist('foo-file')
+
test.write_sample_project('bar.tar.gz')
diff --git a/test/scons-time/run/option/quiet.py b/test/scons-time/run/option/quiet.py
index f5a3d8c..453829c 100644
--- a/test/scons-time/run/option/quiet.py
+++ b/test/scons-time/run/option/quiet.py
@@ -37,28 +37,11 @@ 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,sys
- 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)
- if sys.platform=='darwin':
- # OSX has /tmp in /private/tmp.
- x = '(/private)?' + x
- 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')
+tmp_scons_time = test.tempdir_re()
+tmp_scons_time_foo = test.tempdir_re('foo')
test.write_fake_scons_py()
diff --git a/test/scons-time/run/option/verbose.py b/test/scons-time/run/option/verbose.py
index fb95dab..935e2a9 100644
--- a/test/scons-time/run/option/verbose.py
+++ b/test/scons-time/run/option/verbose.py
@@ -38,28 +38,11 @@ _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,sys
- 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)
- if sys.platform=='darwin':
- # OSX has /tmp in /private/tmp.
- x = '(/private)?' + x
- 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')
+tmp_scons_time = test.tempdir_re()
+tmp_scons_time_foo = test.tempdir_re('foo')
test.write_fake_scons_py()
diff --git a/test/scons-time/run/subversion.py b/test/scons-time/run/subversion.py
index 3839999..757f6df 100644
--- a/test/scons-time/run/subversion.py
+++ b/test/scons-time/run/subversion.py
@@ -60,22 +60,9 @@ test.must_exist('foo-716-0.log',
'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'),
+ test.tempdir_re('src', 'script', 'scons.py'),
+ 'SCONS_LIB_DIR = %s' % test.tempdir_re('src', 'engine'),
]
content = test.read(test.workpath('foo-617-2.log'), mode='r')
diff --git a/test/scons-time/time/empty.py b/test/scons-time/time/empty.py
new file mode 100644
index 0000000..7542bfc
--- /dev/null
+++ b/test/scons-time/time/empty.py
@@ -0,0 +1,91 @@
+#!/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 doesn't fail and prints an appropriate
+error message if a log file is empty.
+"""
+
+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'
+empty_fmt = ' %s\n'
+
+for i in xrange(9):
+ logfile_name = 'foo-%s-0.log' % i
+ if i == 5:
+ test.write(test.workpath(logfile_name), "")
+ lines.append(empty_fmt % logfile_name)
+ else:
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % logfile_name)
+
+expect = [header] + lines
+
+test.run(arguments = 'time foo-*.log',
+ stdout = ''.join(expect),
+ stderr = "file 'foo-5-0.log' has no contents!\n")
+
+expect = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+0 11.123456
+1 11.123456
+2 11.123456
+3 11.123456
+4 11.123456
+6 11.123456
+7 11.123456
+8 11.123456
+e
+"""
+
+stderr = "file 'foo-5-0.log' has no contents!\n"
+
+test.run(arguments = 'time --fmt gnuplot --which total foo-*.log',
+ stdout = expect,
+ stderr = stderr)
+
+expect = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+e
+"""
+
+test.run(arguments = 'time --fmt gnuplot foo-5-0.log',
+ stdout = expect,
+ stderr = stderr)
+
+test.pass_test()
diff --git a/test/scons-time/time/file.py b/test/scons-time/time/file.py
index f4046c9..96bd035 100644
--- a/test/scons-time/time/file.py
+++ b/test/scons-time/time/file.py
@@ -53,16 +53,23 @@ test.run(arguments = 'time -f st1.conf', stdout = expect1)
test.write('st2.conf', """\
prefix = 'foo'
title = 'ST2.CONF TITLE'
+vertical_bars = (
+ ( 1.5, 7, None ),
+)
""")
expect2 = \
r"""set title "ST2.CONF TITLE"
set key bottom left
-plot '-' title "Startup" with lines lt 1
+plot '-' title "Startup" with lines lt 1, \
+ '-' notitle with lines lt 7
# Startup
1 11.123456
2 11.123456
e
+1.5 0
+1.5 12
+e
"""
test.run(arguments = 'time --file st2.conf --fmt gnuplot', stdout = expect2)
diff --git a/test/scons-time/time/no-result.py b/test/scons-time/time/no-result.py
new file mode 100644
index 0000000..ca345b2
--- /dev/null
+++ b/test/scons-time/time/no-result.py
@@ -0,0 +1,75 @@
+#!/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's --which option doesn't fail, and prints
+an appropriate error message, if a log file doesn't have its specific
+requested results.
+"""
+
+import TestSCons_time
+
+test = TestSCons_time.TestSCons_time()
+
+
+header = """\
+set key bottom left
+plot '-' title "Startup" with lines lt 1
+# Startup
+"""
+
+footer = """\
+e
+"""
+
+line_fmt = "%s 11.123456\n"
+
+lines = []
+
+for i in xrange(9):
+ logfile_name = 'foo-%s-0.log' % i
+ if i == 5:
+ test.write(test.workpath(logfile_name), "NO RESULTS HERE!\n")
+ else:
+ test.fake_logfile(logfile_name)
+ lines.append(line_fmt % i)
+
+expect = [header] + lines + [footer]
+
+stderr = "file 'foo-5-0.log' has no results!\n"
+
+
+test.run(arguments = 'time --fmt gnuplot --which total foo*.log',
+ stdout = ''.join(expect),
+ stderr = stderr)
+
+expect = [header] + [footer]
+
+test.run(arguments = 'time --fmt gnuplot foo-5-0.log',
+ stdout = ''.join(expect),
+ stderr = stderr)
+
+test.pass_test()
diff --git a/test/subclassing.py b/test/subclassing.py
index 18be1bc..31632a9 100644
--- a/test/subclassing.py
+++ b/test/subclassing.py
@@ -25,7 +25,9 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-Verify that we can trivially subclass our "public" classes.
+Verify that we can trivially subclass our "public" classes. Also
+verify that we can use a trivial subclass of new-style str classes
+as well as UserString as Builder input.
"""
import TestSCons
@@ -33,6 +35,8 @@ import TestSCons
test = TestSCons.TestSCons()
test.write('SConstruct', """
+copy_action = Copy('$TARGET', '$SOURCE')
+
# Some day, we'd probably like people to be able to subclass Action and
# Builder, but that's going to take some serious class-hackery to turn
# our factory function into the class itself.
@@ -45,18 +49,31 @@ class my_Scanner(Scanner):
class my_Environment(Environment):
pass
env = my_Environment()
-env.Program('hello', 'hello.c')
-""")
+env.Command('f0.out', 'f0.in', copy_action)
+
+from UserString import UserString
+try:
+ class mystr(str):
+ pass
+except TypeError:
+ class mystr(UserString):
+ pass
-test.write('hello.c', """\
-#include <stdio.h>
-#include <stdlib.h>
-int
-main(int argc, char *argv[]) {
- printf("hello.c\\n");
-}
+Command(mystr('f1.out'), mystr('f1.in'), copy_action)
+Command(UserString('f2.out'), UserString('f2.in'), copy_action)
+
+Install(mystr('install'), mystr('f1.out'))
+Install(mystr('install'), UserString('f2.out'))
""")
+test.write('f0.in', "f0.in\n")
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+
test.run(arguments = '.')
+test.must_match('f0.out', "f0.in\n")
+test.must_match(['install', 'f1.out'], "f1.in\n")
+test.must_match(['install', 'f2.out'], "f2.in\n")
+
test.pass_test()
diff --git a/test/timestamp-fallback.py b/test/timestamp-fallback.py
index 9d89d70..0774995 100644
--- a/test/timestamp-fallback.py
+++ b/test/timestamp-fallback.py
@@ -79,7 +79,8 @@ test.write('f2.in', "f2.in\n")
test.write('f3.in', "f3.in\n")
test.write('f4.in', "f4.in\n")
-test.run(arguments = 'f1.out f3.out')
+test.run(arguments = 'f1.out f3.out',
+ stderr = None)
test.run(arguments = 'f1.out f2.out f3.out f4.out',
stdout = test.wrap_stdout("""\
@@ -87,7 +88,8 @@ scons: `f1.out' is up to date.
build(["f2.out"], ["f2.in"])
scons: `f3.out' is up to date.
build(["f4.out"], ["f4.in"])
-"""))
+"""),
+ stderr = None)
os.utime(test.workpath('f1.in'),
(os.path.getatime(test.workpath('f1.in')),
@@ -102,7 +104,8 @@ build(["f1.out"], ["f1.in"])
scons: `f2.out' is up to date.
build(["f3.out"], ["f3.in"])
scons: `f4.out' is up to date.
-"""))
+"""),
+ stderr = None)
test.pass_test()