summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2007-09-19 12:52:29 (GMT)
committerSteven Knight <knight@baldmt.com>2007-09-19 12:52:29 (GMT)
commitd43c3fa04d636344c9d38794182970914a85ce0b (patch)
tree0c824d7694f6a54b5fae780cfca8d04cb02b85bc /test
parenteecd55b0591926f04dc812088702587ab1d6cc10 (diff)
downloadSCons-d43c3fa04d636344c9d38794182970914a85ce0b.zip
SCons-d43c3fa04d636344c9d38794182970914a85ce0b.tar.gz
SCons-d43c3fa04d636344c9d38794182970914a85ce0b.tar.bz2
Merged revisions 2302-2362,2364-2452 via svnmerge from
http://scons.tigris.org/svn/scons/branches/core ................ r2311 | stevenknight | 2007-08-17 07:51:31 -0500 (Fri, 17 Aug 2007) | 2 lines Fix the CHECKPOINT= help text. ................ r2313 | stevenknight | 2007-08-17 13:12:13 -0500 (Fri, 17 Aug 2007) | 2 lines Make sure the --debug=time works when -h is specified, too. ................ r2320 | stevenknight | 2007-08-18 08:54:49 -0500 (Sat, 18 Aug 2007) | 3 lines Don't execute any Configure() actions while reading SConscript files when -c or -h or -H are specified. ................ r2321 | stevenknight | 2007-08-20 08:48:57 -0500 (Mon, 20 Aug 2007) | 2 lines Cleaner test failure if before-and-after PostScript files don't match. ................ r2322 | stevenknight | 2007-08-20 11:02:57 -0500 (Mon, 20 Aug 2007) | 2 lines Remove function definitions that make some Java versions fail. ................ r2354 | stevenknight | 2007-08-20 14:26:13 -0500 (Mon, 20 Aug 2007) | 3 lines Relax test conditions for two scripts that have differing behavior under different versions of Java + SWIG (+ gcc...?). ................ r2355 | stevenknight | 2007-08-20 14:29:36 -0500 (Mon, 20 Aug 2007) | 2 lines Fix the SConstruct file so it doesn't die if Subversion isn't installed. ................ r2356 | stevenknight | 2007-08-20 22:26:35 -0500 (Mon, 20 Aug 2007) | 3 lines Update to latest Test{Cmd,Common}.py, with better avoidance of race conditions on temporary file and directory names. ................ r2373 | stevenknight | 2007-08-27 10:47:21 -0500 (Mon, 27 Aug 2007) | 2 lines Windows portability fixes in tests. ................ r2377 | stevenknight | 2007-08-27 12:33:47 -0500 (Mon, 27 Aug 2007) | 2 lines Add a null command list to suppress the baseline build when testing. ................ r2380 | stevenknight | 2007-08-27 16:33:42 -0500 (Mon, 27 Aug 2007) | 616 lines Merged revisions 1503-1543,1545-1546,1548-1558,1560-1562,1564-1886,1888-1909,1911-1941,1943,1945-1955,1957-1960,1962-1963,1965-1999,2001-2019,2021-2037,2039-2061,2063-2067,2069-2146,2148-2150,2152-2156,2158-2199,2201-2208,2210-2212,2214-2238,2240,2242-2288,2290-2291,2293-2305,2307-2364,2366-2373,2375-2377,2379 via svnmerge from http://scons.tigris.org/svn/scons/branches/sigrefactor ........ r1550 | stevenknight | 2006-07-27 21:40:08 -0500 (Thu, 27 Jul 2006) | 3 lines First cut at storing csig separately in the NodeInfo, but still using bsigs for up-to-date checks. ........ r1551 | stevenknight | 2006-07-28 07:07:27 -0500 (Fri, 28 Jul 2006) | 2 lines Refactor the use of dictify() to avoid __builtin__ issues with zip on 1.5. ........ r1552 | stevenknight | 2006-07-28 10:05:18 -0500 (Fri, 28 Jul 2006) | 3 lines Have msvsTests.py print why it's not executing tests when on a non-win32 system. ........ r1553 | stevenknight | 2006-07-28 11:28:37 -0500 (Fri, 28 Jul 2006) | 3 lines Refactor when NodeInfo objects get instantiated (when requested explicitly, not as a side effect of creating a BuildInfo object). ........ r1554 | stevenknight | 2006-07-28 11:42:53 -0500 (Fri, 28 Jul 2006) | 3 lines Refactor test/{Source,Target}Signatures.py to make changing their semantics easier. ........ r1555 | stevenknight | 2006-07-28 13:18:35 -0500 (Fri, 28 Jul 2006) | 6 lines Eliminate use of build signatures, changing interfaces and semantics of SourceSignature() and TargetSignatures(), accordingly. Make use of content signatures the default behavior. Get rid of most uses the Sig/*.py calculator modules and passing around a "calc" argument everywhere. ........ r1556 | stevenknight | 2006-07-28 15:14:03 -0500 (Fri, 28 Jul 2006) | 3 lines Fix use of CacheDir() with Alias and Value Nodes. Refactor sub-tests in test/CacheDir.py into separate test scripts. ........ r1557 | stevenknight | 2006-07-28 21:40:31 -0500 (Fri, 28 Jul 2006) | 2 lines Finish the necessary coding to remove the no-longer-needed Sig/*.py modules. ........ r1560 | stevenknight | 2006-07-29 05:52:27 -0500 (Sat, 29 Jul 2006) | 3 lines Move current_*() methods for the different flavors of file comparison into (e.g.) the Node.FS.File class itself, not its FileNodeInfo class. ........ r1562 | stevenknight | 2006-07-29 08:46:23 -0500 (Sat, 29 Jul 2006) | 2 lines Fix the default returned Boolean value of changed_{content,timestamp}(). ........ r1564 | stevenknight | 2006-07-29 10:51:24 -0500 (Sat, 29 Jul 2006) | 3 lines Fix the --debug=explain option. Move test/explain.py to test/option/debug-explain.py. ........ r1565 | stevenknight | 2006-07-29 16:09:31 -0500 (Sat, 29 Jul 2006) | 2 lines Refactor Taskmaster to visit source file Nodes in its walk. ........ r1566 | stevenknight | 2006-07-29 17:50:38 -0500 (Sat, 29 Jul 2006) | 4 lines Merge Node.FS._cur2() into Node.FS.is_up_to_date(). Use a Node.FS.*.make_ready() to handle disambiguation. Split the guts of has_src_builder() into a separate find_src_builder() method. ........ r1567 | stevenknight | 2006-07-29 17:55:36 -0500 (Sat, 29 Jul 2006) | 2 lines Make the sconsign script print the stored action information. ........ r1568 | stevenknight | 2006-07-29 17:59:03 -0500 (Sat, 29 Jul 2006) | 2 lines Refactor for test readability. ........ r1569 | stevenknight | 2006-07-29 20:32:26 -0500 (Sat, 29 Jul 2006) | 2 lines Get rid of the now-unnecessary "module" argument to SConsign methods. ........ r1570 | stevenknight | 2006-07-29 22:05:47 -0500 (Sat, 29 Jul 2006) | 3 lines Move content signature calcuation to an explicit make_ready() function. Collect NodeInfo field updating in the base class. ........ r1571 | stevenknight | 2006-07-30 06:26:17 -0500 (Sun, 30 Jul 2006) | 2 lines Eliminte the no-longer-necessary is_pseudo_derived() method. ........ r1572 | stevenknight | 2006-07-30 07:53:40 -0500 (Sun, 30 Jul 2006) | 2 lines Add tgt_sig_type arguments to various changed() methods' calling arguments. ........ r1573 | stevenknight | 2006-07-30 08:17:43 -0500 (Sun, 30 Jul 2006) | 2 lines More informative output from test/SideEffect.py when it fails. ........ r1574 | stevenknight | 2006-07-30 09:53:11 -0500 (Sun, 30 Jul 2006) | 3 lines Restore the ability to fall back gracefully to timestamps if the running version of Python has no md5 module available. ........ r1575 | stevenknight | 2006-08-02 20:21:04 -0500 (Wed, 02 Aug 2006) | 3 lines Fix a failing Qt test by calling disambiguate() before make_ready() for all of the targets in a list, not just the first. ........ r1646 | stevenknight | 2006-10-17 17:21:58 -0500 (Tue, 17 Oct 2006) | 6 lines Move all the scons.org stuff from the scons source tree itself to a directory next to the trunk, and delete the copies from the branches. There's a lot of stuff there (what with all of the documentation of the different versions) and it's ridiculous to make everyone sync it just to work on the code. ........ r1888 | stevenknight | 2007-04-17 14:57:47 -0500 (Tue, 17 Apr 2007) | 2 lines More efficient/cleaner code for dictifying --debug=explain info. ........ r1889 | stevenknight | 2007-04-17 15:55:00 -0500 (Tue, 17 Apr 2007) | 3 lines More efficient taskmaster: filter the list once for anything that hasn't been built, then extract a sub-list of anything that hasn't been visited. ........ r1894 | stevenknight | 2007-04-25 13:07:29 -0500 (Wed, 25 Apr 2007) | 4 lines Push conversion of individual NodeInfo objects into the objects themselves (instead of having the FileBuildInfo class assume that every dependency is a file system Entry of some kind). ........ r1895 | stevenknight | 2007-05-04 23:49:13 -0500 (Fri, 04 May 2007) | 3 lines Store content signatures for Aliases so we can really use them as dependencies. ........ r1896 | stevenknight | 2007-05-07 16:37:06 -0500 (Mon, 07 May 2007) | 3 lines Move the TargetSignatures.py test into a subdirectory, which we can populate with other tests (of the new settings, etc.). ........ r1897 | stevenknight | 2007-05-07 17:36:04 -0500 (Mon, 07 May 2007) | 3 lines Fix use of TargetSignatures('content') to override settings of SourceSignatures('timestamp'). ........ r1900 | stevenknight | 2007-05-14 18:48:39 -0500 (Mon, 14 May 2007) | 5 lines More specific sconsign signature tests: check for an actual 32-digit-long hex string when an MD5 checksum is expected, so we can correctly detect test failures if "None" shows up instead. (This will be used for getting avoiding calculating the content signature in 'timestamp' mode.) ........ r1949 | stevenknight | 2007-05-30 22:45:25 -0500 (Wed, 30 May 2007) | 7 lines Refactor the get_{csig,timestamp,size}() methods so they use the Memoizer pattern, instead of the the NodeInfo object, to cache the results. This won't be the final form (we have to reach and stuff a csig value in the cache slot to make --implicit-cache work) but it's a step that should make it easier to work on other in-progress modifications. ........ r1957 | stevenknight | 2007-06-01 10:18:15 -0500 (Fri, 01 Jun 2007) | 14 lines Shift updating a Node's signature/timestamp/size information until after the Node has been built (or visited, if it's a leaf Node). This therefore changes the semantics of the .visited() method, so that it's called for *every* Node visited, not just leaf Nodes. This adds a Taskmaster method for updating a Node's status without calling the .built() and .visited() methods, which is used by the CleanTask subclass to avoid writing .sconsign info when cleaning (-c). Interesting ripple effect in the SConf.py module: we have to manually override the .store_info() method on the Nodes we create, so that they don't write out their normal .sconsign information. The SConf subsystem writes out its own by hand. ........ r1962 | stevenknight | 2007-06-01 13:12:24 -0500 (Fri, 01 Jun 2007) | 5 lines Fix the ability to catch {IO,OS}Errors during build preparation and display the actual Node that triggered the error. (Which Node actually triggers this case, and therefore the displayed error message, changed after we delayed content evaluation until *after* a Node is built.) ........ r1975 | stevenknight | 2007-06-04 15:21:09 -0500 (Mon, 04 Jun 2007) | 3 lines Small refactoring: use {new,get}_ninfo() instead of instantiating self.NodeInfo() directly. ........ r1976 | stevenknight | 2007-06-04 16:14:12 -0500 (Mon, 04 Jun 2007) | 5 lines Similar to the previous change, call new_binfo() instead of instantiating the BuildInfo() type directly. Change new_binfo() so it doesn't automatically attach a NodeInfo object (because sometimes we want the existing NodeInfo, and sometimes we want a completely new one). ........ r1977 | stevenknight | 2007-06-04 16:35:44 -0500 (Mon, 04 Jun 2007) | 3 lines The body of DirFile.write() was all indented underneath a "if self.dirty:" block. Invert the test and outdent the body. ........ r1978 | stevenknight | 2007-06-04 16:52:14 -0500 (Mon, 04 Jun 2007) | 2 lines Memoize the stored information we get from the .sconsign file. ........ r1979 | stevenknight | 2007-06-05 14:17:32 -0500 (Tue, 05 Jun 2007) | 6 lines Delay merging a Node's build information into the .sconsign entry until the entry is being written out. This will allow us to include information (such as a content signature) that gets fetched for the first time *after* a Node is built. (The code here isn't the prettiest at the moment, but this checkpoints an implementation that passes all the tests.) ........ r1980 | stevenknight | 2007-06-06 10:06:56 -0500 (Wed, 06 Jun 2007) | 4 lines Refactor to have the store_info() method pull the binfo from the Node (instead of having the Node passing it in). Add a do_not_store_info() method to override the behavior. ........ r1981 | stevenknight | 2007-06-06 11:18:29 -0500 (Wed, 06 Jun 2007) | 3 lines Refactor the unit test invocation so we can run multiple test methods from each class. ........ r1982 | stevenknight | 2007-06-06 11:48:00 -0500 (Wed, 06 Jun 2007) | 7 lines Move responsibility for merging buildinfo entries from Node.FS to the SConsign module, through a new Base.store_info() method. Return the existing Base.set_entry() method to actually setting the entry, and use the new Base.store_info() method for things that need delayed storage and merging. Adds some commented-out prototype code for delaying the buildinfo entry merge until later. ........ r1983 | stevenknight | 2007-06-06 22:57:14 -0500 (Wed, 06 Jun 2007) | 4 lines Better testing for parallel-build exceptions: re-order the file names so that the input files are evaluated before the output files, increasing the likelihood of all three being built by simultaneous threads. ........ r1984 | stevenknight | 2007-06-06 22:57:55 -0500 (Wed, 06 Jun 2007) | 2 lines Have Trace() flush after write so interleaving stays correct. ........ r1985 | stevenknight | 2007-06-06 23:01:23 -0500 (Wed, 06 Jun 2007) | 11 lines Pull the NodeInfo objects out of the BuildInfo object and just deal with them as co-equal attributes of a Node. .sconsign files now have a place-holder SConsignEntry class that holds a Node's separate binfo and ninfo objects. This will also be more flexible if we ever add more information in the future. Since this changes the format (but not content) of the .sconsign file entries, we will need to double back and figure out how to make the transition from pre-BSR .sconsign files before this goes live. ........ r1986 | stevenknight | 2007-06-07 00:08:21 -0500 (Thu, 07 Jun 2007) | 2 lines Store the computed csig in the NodeInfo structure. ........ r1987 | stevenknight | 2007-06-07 18:59:31 -0500 (Thu, 07 Jun 2007) | 12 lines Track the content signature directly in the NodeInfo object, not in the _memo dictionary. Wipe out the existing NodeInfo after the Node has been built so the content signature gets recalculated correctly. Change the NodeInfoBase.update() method so that the default behavior is to always update the specified fields, not just ones that exist. This was necessary to get Alias and Value Nodes to work with this. Remove left-over comments. ........ r1988 | stevenknight | 2007-06-08 17:09:24 -0500 (Fri, 08 Jun 2007) | 5 lines Invert the logic (is_up_to_date => changed) when gathering Configure Node states, and eliminate (most) Boolean logic that short-circuits some of the tests. (This area isn't critical, so making sure the code is readable is more important than pure performance.) ........ r1990 | stevenknight | 2007-06-09 17:14:32 -0500 (Sat, 09 Jun 2007) | 7 lines Refactor the Node.changed() method so it always evaluates every dependency, instead of returning early as soon as it finds a difference (like a different number of old and new dependencies). This will be necessary to delay evaluation of Node information (content signatures) until it's actually needed (instead of evaluating it up front in case it's needed later). ........ r2001 | stevenknight | 2007-06-11 11:20:29 -0500 (Mon, 11 Jun 2007) | 3 lines Use SCons.compat in the refactored SConsign.py so use of True/False/etc. works on Python 1.5 and 2.1. ........ r2002 | stevenknight | 2007-06-11 11:57:56 -0500 (Mon, 11 Jun 2007) | 3 lines Have the "sconsign" script handle Configure context .sconsign information, which comes from different structures that have no NodeInfo objects. ........ r2003 | stevenknight | 2007-06-11 15:08:52 -0500 (Mon, 11 Jun 2007) | 8 lines Avoid generating content signatures unless they're actually used: Don't automatically create a content signature after a File Node is built/visited, and delay the .sconsign merge of the information until just before the information will be written. This means we'll only write out information that's actually fetched and used as part of deciding whether or not to rebuild any targets. ........ r2004 | stevenknight | 2007-06-13 00:05:52 -0500 (Wed, 13 Jun 2007) | 4 lines Fetch the {Source,Target}Signatures() values inside the Node.FS.changed_since_last_build() method, not in Node.Node.changed(). This is slightly less efficient, but cleaner architecturally. ........ r2005 | stevenknight | 2007-06-13 10:18:17 -0500 (Wed, 13 Jun 2007) | 6 lines Use zip() to collect the children and previous signatures info more efficiently when deciding if a node must be rebuilt. (The comment in the previous version of the source code about not using zip() because of Python 1.5 name space problems was due to the way the SConfTests.py module tried to reset the world's state.) ........ r2006 | stevenknight | 2007-06-13 10:59:16 -0500 (Wed, 13 Jun 2007) | 4 lines Add a NotImplementedError base class implementation of changed_since_last_build(), with doc string commentary about why the method is called through the dependency Node, not the target Node. ........ r2019 | stevenknight | 2007-06-18 12:26:06 -0500 (Mon, 18 Jun 2007) | 4 lines Remove the unnecessary cut-and-paste "import SCons.Action" in the changed_since_last_build() method, which was a left-over cut and paste. SCons.Action was already imported up top. ........ r2021 | stevenknight | 2007-06-18 18:31:09 -0500 (Mon, 18 Jun 2007) | 2 lines Make sure all "is up to date" messages get printed when -j is used. ........ r2022 | stevenknight | 2007-06-19 16:26:22 -0500 (Tue, 19 Jun 2007) | 3 lines Refactor the __checkClass() and must_be_a_Dir() methods into a more general and more efficient must_be_same() method. ........ r2024 | stevenknight | 2007-06-19 19:16:09 -0500 (Tue, 19 Jun 2007) | 3 lines More clean up: change various self.fs.Entry() calls to calls through the bound directory.Entry() method. ........ r2026 | stevenknight | 2007-06-19 22:10:04 -0500 (Tue, 19 Jun 2007) | 10 lines Refactor lookup of Node.FS nodes as follows: * Completely get rid of _doLookup(), which was old, complicated code that implemented a top-down, entry-by-entry search for path names. * Use a new FS._lookup() method, which normalizes names to absolute paths, with a new RootDir._lookup_abs() method, which handles the actual lookup. We plan to use the latter method for fast(er) internal lookups of already-normalized paths. * Create a new separate FS.get_root() method, just to avoid clutter in the RootDir._lookup_abs() method. ........ r2027 | stevenknight | 2007-06-20 13:29:19 -0500 (Wed, 20 Jun 2007) | 3 lines Remove the debug-explain.py test from sigrefactor, branches/core split this up into multiple sub-tests. ........ r2028 | stevenknight | 2007-06-20 13:38:28 -0500 (Wed, 20 Jun 2007) | 2 lines Handle a line-ending mismatch on Windows. ........ r2029 | stevenknight | 2007-06-20 13:39:05 -0500 (Wed, 20 Jun 2007) | 2 lines Support the ability to -d when path names have Windows \ separators. ........ r2030 | stevenknight | 2007-06-20 13:55:11 -0500 (Wed, 20 Jun 2007) | 2 lines Windows portability: TestSConsign._obj instead of a hard-coded '.o' suffix. ........ r2031 | stevenknight | 2007-06-20 15:30:06 -0500 (Wed, 20 Jun 2007) | 2 lines Python 1.5 namespace portability. ........ r2032 | stevenknight | 2007-06-20 16:38:28 -0500 (Wed, 20 Jun 2007) | 2 lines Fix tests affected by the -d fix for runtest.py. ........ r2039 | stevenknight | 2007-06-21 12:17:06 -0500 (Thu, 21 Jun 2007) | 2 lines Ignore *.pyo files, too, now that one of the tests causes us to generate them. ........ r2041 | stevenknight | 2007-06-21 12:36:30 -0500 (Thu, 21 Jun 2007) | 7 lines In the .sconsign file, store the paths to all of the dependencies relative to the top-level SConstruct directory, not the target's directory. This allows us to be much more efficient when writing the .sconsign file (since we can just store the already-computed path) and reading the .sconsign file (since we can use the quick, normalized-lookup method to translate the string into the correct Node). ........ r2042 | stevenknight | 2007-06-22 13:25:26 -0500 (Fri, 22 Jun 2007) | 2 lines Remove left-over debug code (instrumenting os.path.normpath()). ........ r2043 | stevenknight | 2007-06-22 13:28:35 -0500 (Fri, 22 Jun 2007) | 8 lines Actually use the new Dir._lookup_abs() method for fast .sconsign lookups relative to the top-level SConstruct directory and make it work correctly. (I had commented out the call to binfo.prepare_dependencies() and forgot to un-comment it.) This simplifies things by getting rid of the target node we attached to a BuildInfo (purely so we could do relative path lookups) and the corresponding conversions into and out of the .sconsign file. ........ r2044 | stevenknight | 2007-06-22 19:31:00 -0500 (Fri, 22 Jun 2007) | 5 lines Delay fetching the {Source,Target}Signature() values from an environment until they're actually needed. (If the performance here is "close enough", then we may not have to look at more complicated loop-invariant schemes.) ........ r2045 | stevenknight | 2007-06-22 22:06:19 -0500 (Fri, 22 Jun 2007) | 4 lines Replace the Environment.our_deepcopy() function with a Util.semi_deepcopy() function, rewritten to use the more efficient dispatch-table approach that the normal Python copy.py module uses. ........ r2050 | stevenknight | 2007-06-24 23:49:06 -0500 (Sun, 24 Jun 2007) | 5 lines Make the latest signature refactoring portable to Windows, and between platforms, by always storing the dependency paths with POSIX separators. Handle multiple drive letters by tracking a separate "labspath" attribute for the lookup path relative to the root directory's drive letter. ........ r2065 | stevenknight | 2007-06-27 11:02:48 -0500 (Wed, 27 Jun 2007) | 2 lines Branch files that were left out of the last merge. ........ r2066 | stevenknight | 2007-06-27 11:03:05 -0500 (Wed, 27 Jun 2007) | 2 lines Branch files that were left out of the last merge. ........ r2067 | stevenknight | 2007-06-27 11:03:24 -0500 (Wed, 27 Jun 2007) | 2 lines Branch files that were left out of the last merge. ........ r2069 | stevenknight | 2007-06-27 19:08:50 -0500 (Wed, 27 Jun 2007) | 2 lines Remove an unnecessary target.has_builder() call in changed_since_last_build(). ........ r2070 | stevenknight | 2007-06-27 19:25:47 -0500 (Wed, 27 Jun 2007) | 3 lines Refactor changed_since_last_build() to avoid code duplication and simplify (?) the structure--probably negligible performance impact. ........ r2071 | stevenknight | 2007-06-29 16:21:37 -0500 (Fri, 29 Jun 2007) | 3 lines Add the Decider() function, globally, and settable per construction environment or per Node. This hasn't yet been optimized. ........ r2072 | stevenknight | 2007-06-29 18:01:53 -0500 (Fri, 29 Jun 2007) | 2 lines Memoize Executor.get_build_env(). ........ r2073 | stevenknight | 2007-06-30 01:04:43 -0500 (Sat, 30 Jun 2007) | 5 lines Constructing a dictionary to map signature types ('build', 'MD5', etc.) to a dependency's methods ends up being less efficient than just using a series of if-elif statements. Refactor the default_decider_function() accordingly. ........ r2074 | stevenknight | 2007-07-01 08:59:35 -0500 (Sun, 01 Jul 2007) | 4 lines Now that the objects returned by Node.FS.get_stored_implicit() already convert the .sconsign strings to Nodes, don't have the --implicit-cache loop run them through the source_factory method. ........ r2075 | stevenknight | 2007-07-02 09:46:21 -0500 (Mon, 02 Jul 2007) | 4 lines Eliminate an if-test for the intialized default construction environment for internal calls of SCons.Defaults.DefaultEnvironment(), and some external calls as well. ........ r2076 | stevenknight | 2007-07-02 10:17:58 -0500 (Mon, 02 Jul 2007) | 3 lines More efficient use of the changed_since_last_build() method from the default construction environment. ........ r2077 | stevenknight | 2007-07-02 12:26:34 -0500 (Mon, 02 Jul 2007) | 6 lines Move the decision about whether a given dependent Node has a Builder or not back to when the Builder is actually set, by splitting the decision path in two; one for sources and one for targets. (Setting a construction environment's decider sets both of them, which may or may not be what we want in the long term.)) ........ r2079 | stevenknight | 2007-07-02 13:14:40 -0500 (Mon, 02 Jul 2007) | 4 lines Now explicity set the source decider function for a construction environment when the SourceSignatures() method is called, avoiding the delayed-evaluation tests. ........ r2081 | stevenknight | 2007-07-02 13:55:58 -0500 (Mon, 02 Jul 2007) | 6 lines And now explicity set the target decider function for a construction environment when the TargetSignatures() method is called, avoiding even more delayed-evaluation tests. This also renames the cslb_*() functions to decide_*(). ........ r2084 | stevenknight | 2007-07-03 07:13:38 -0500 (Tue, 03 Jul 2007) | 3 lines Memoize the Node.get_build_env() value, too, since we're now callng that repeatedly. ........ r2085 | stevenknight | 2007-07-03 09:50:25 -0500 (Tue, 03 Jul 2007) | 5 lines Get rid of the str_to_nodes() function within the FileBuildInfo.prepare_dependencies() method that checks for Alias lookups, in favor of a loop that uses new str_to_nodes() methods in the individual *NodeInfo classes to convert the strings to Nodes more directly. ........ r2086 | stevenknight | 2007-07-03 10:07:04 -0500 (Tue, 03 Jul 2007) | 3 lines Format the FileBuildInfo entries by zipping the children and their NodeInfo signatures, not by fetching each one by index. ........ r2089 | stevenknight | 2007-07-03 20:20:15 -0500 (Tue, 03 Jul 2007) | 4 lines Remove the _add_child() checks that verify that the argument is a list and contains all Nodes. It's internal, so any necessary verification can happen in the methods that call it. ........ r2101 | stevenknight | 2007-07-08 16:13:56 -0500 (Sun, 08 Jul 2007) | 3 lines Add string aliases for the canned Decider functions we'll support out of the box: timestamp-match (a.k.a. make), timestamp-newer, MD5 (a.k.a. content). ........ r2115 | stevenknight | 2007-07-10 21:00:14 -0500 (Tue, 10 Jul 2007) | 2 lines Refactor test/option-q.py into two separate subtests. ........ r2144 | stevenknight | 2007-07-16 01:04:25 -0500 (Mon, 16 Jul 2007) | 3 lines Fix -q exiting with a non-zero exit status when a file with no builder is specified on the command line. ........ r2314 | stevenknight | 2007-08-17 13:46:27 -0500 (Fri, 17 Aug 2007) | 3 lines Capture a test case to make sure get_csig() can be called from within a function Action. (Damyan Pepper) ........ r2315 | stevenknight | 2007-08-17 15:05:54 -0500 (Fri, 17 Aug 2007) | 3 lines Uncomment the test for content signatures with directories as sources, which the signature refactoring makes work. ........ r2316 | stevenknight | 2007-08-17 16:33:25 -0500 (Fri, 17 Aug 2007) | 2 lines Make sure that CacheDir() works even when timestamp signatures are used. ........ r2317 | stevenknight | 2007-08-17 16:51:02 -0500 (Fri, 17 Aug 2007) | 2 lines Change line endings from DOS to UNIX. ........ r2318 | stevenknight | 2007-08-18 07:13:09 -0500 (Sat, 18 Aug 2007) | 4 lines Add a new MD5-timestamp decider function that assumes that if the timestamp hasn't changed, then the content hasn't changed either, and it should then just re-use the content signature from the last run. ........ r2319 | stevenknight | 2007-08-18 07:41:59 -0500 (Sat, 18 Aug 2007) | 3 lines Add a test script to verify that action changes cause rebuilds even when file decisions are configured for timestamps. ........ r2360 | stevenknight | 2007-08-23 08:07:16 -0500 (Thu, 23 Aug 2007) | 2 lines Fix the test by resetting the content3.in file to the correct timestamp. ........ r2361 | stevenknight | 2007-08-23 12:02:04 -0500 (Thu, 23 Aug 2007) | 3 lines Use the new hashlib module for our MD5 signature calculations, with the introduction of a compatibility module for pre-2.5 Python versions. ........ r2362 | stevenknight | 2007-08-23 14:02:56 -0500 (Thu, 23 Aug 2007) | 2 lines Make targets implicitly depend on the commands used to build them. ........ r2364 | stevenknight | 2007-08-24 00:07:46 -0500 (Fri, 24 Aug 2007) | 2 lines Add code to convert what we can from the old .sconsign file entries. ........ r2366 | stevenknight | 2007-08-24 19:40:09 -0500 (Fri, 24 Aug 2007) | 2 lines Add a $IMPLICIT_COMMAND_DEPENDENCIES variable. ........ r2367 | stevenknight | 2007-08-24 19:43:58 -0500 (Fri, 24 Aug 2007) | 2 lines Add mention of $IMPLICIT_COMMAND_DEPENDENCIES to the release notes. ........ r2375 | stevenknight | 2007-08-27 11:43:04 -0500 (Mon, 27 Aug 2007) | 2 lines Windows portability fixes in tests. ........ r2376 | stevenknight | 2007-08-27 12:19:52 -0500 (Mon, 27 Aug 2007) | 2 lines Use string.join() instead of a more modern string object method. ........ r2379 | stevenknight | 2007-08-27 12:40:02 -0500 (Mon, 27 Aug 2007) | 3 lines Add version ID's to the classes stored in a .sconsign file, for easier future conversion as we change schemas. ........ ................ r2390 | stevenknight | 2007-08-27 17:32:00 -0500 (Mon, 27 Aug 2007) | 4 lines Remove the old TargetSignatures.py test, which was overlooked in the merge. (Its functionality got moved to test/TargetSignatures/build-content.py.) ................ r2391 | stevenknight | 2007-08-28 10:47:15 -0500 (Tue, 28 Aug 2007) | 2 lines Don't die if an old .sconsign entry has no .ninfo attribute. ................ r2392 | stevenknight | 2007-08-28 15:52:56 -0500 (Tue, 28 Aug 2007) | 2 lines Fix an O(N^2) search in Tool.install.add_targets_to_INSTALLED_FILES(). ................ r2393 | stevenknight | 2007-08-28 21:28:30 -0500 (Tue, 28 Aug 2007) | 2 lines Add support for an ensure_suffix Builder keyword argument. ................ r2394 | stevenknight | 2007-08-28 21:37:04 -0500 (Tue, 28 Aug 2007) | 3 lines Separate the failure tests when trying to connect to an X server, so we can tell why it's failing... ................ r2395 | stevenknight | 2007-08-29 11:46:34 -0500 (Wed, 29 Aug 2007) | 3 lines Look for a raw exit status of 1, or the shifted exit status, so we're not dependent on how the test infrastructure hands it to us. ................ r2396 | stevenknight | 2007-08-29 18:12:39 -0500 (Wed, 29 Aug 2007) | 2 lines Disable universal_newlines when calling subprocess. ................ r2397 | stevenknight | 2007-08-29 18:13:29 -0500 (Wed, 29 Aug 2007) | 3 lines Add a Progress() hook to support display of per-Node progress while walking the DAG. ................ r2398 | stevenknight | 2007-08-29 19:43:12 -0500 (Wed, 29 Aug 2007) | 7 lines Add a test case (courtesy Greg Noel) to characterize how we handle mid-build changes to implicit dependency files (we currently don't detect the change and rebuild all dependents). Move two other test scripts related to implicit dependency behavior into a common subdirectory. ................ r2399 | stevenknight | 2007-08-30 10:32:50 -0500 (Thu, 30 Aug 2007) | 4 lines Add a $JAVABOOTCLASSPATH variable. Commonize $JAVA*PATH expansion with a utility class. (Greg Ward) ................ r2400 | stevenknight | 2007-08-30 10:59:56 -0500 (Thu, 30 Aug 2007) | 3 lines Make sure extra auxiliary files generated by LaTeX packages are deleted by scons -c. (Matthias Troffaes) ................ r2401 | stevenknight | 2007-08-30 18:43:24 -0500 (Thu, 30 Aug 2007) | 3 lines Issue 1589: when Cloning a construction environment, apply set variables both before and after calling tools (like during intialization). ................ r2402 | stevenknight | 2007-08-30 18:52:02 -0500 (Thu, 30 Aug 2007) | 3 lines Issue 1555: add Windows64 support for the Intel C compiler. (Gary Oberbrunner) ................ r2403 | stevenknight | 2007-08-30 19:57:24 -0500 (Thu, 30 Aug 2007) | 4 lines Issue 1493: have ParseConfig(), MergeFlags() and ParseFlags() handle output from *-config commands with quoted arguments (path names that contain spaces). ................ r2410 | stevenknight | 2007-09-04 00:28:46 -0500 (Tue, 04 Sep 2007) | 4 lines Add a shlex.split() compatability wrapper for pre-Python 2.3 versions. Unfortunately, it doesn't behave exactly like later versions (it doesn't detect mid-token quotes), but we're not going to worry about that. ................ r2411 | stevenknight | 2007-09-04 12:56:36 -0500 (Tue, 04 Sep 2007) | 3 lines Add a Sig.py module that generates a warning if user code tries to "import SCons.Sig" directly. ................ r2412 | stevenknight | 2007-09-04 20:53:09 -0500 (Tue, 04 Sep 2007) | 3 lines Make the Return() function return immediately. Add a stop= keyword argument in case anyone really needs the old behavior. ................ r2413 | stevenknight | 2007-09-05 10:38:40 -0500 (Wed, 05 Sep 2007) | 4 lines Refactor initialization of different pieces (the underlying InstallBuilder, the Install() and InstallAs() wrappers) into separate blocks. ................ r2414 | stevenknight | 2007-09-05 11:39:25 -0500 (Wed, 05 Sep 2007) | 4 lines Move the definitions of the wrapper functions to the global namespace (nesting them and delaying intialization of global variables doesn't save anything and just complicates reading the code). ................ r2415 | stevenknight | 2007-09-05 13:31:27 -0500 (Wed, 05 Sep 2007) | 3 lines When Cloning a construction environment, re-bind any methods added by the AddMethod() method to the new construction environment. ................ r2416 | stevenknight | 2007-09-06 10:04:18 -0500 (Thu, 06 Sep 2007) | 7 lines Add a MethodWrapper class that handles generic association of a callable and an object that wants to use the callable as a "method." Provide hooks for centralized cloning of the different "methods" on to a new, copied underlying environment (used by the env.Clone() method). Make BuilderWrapper a subclass of MethodWrapper. Modify env.Clone() for the new, combined way of handling these "methods." ................ r2417 | stevenknight | 2007-09-06 14:11:35 -0500 (Thu, 06 Sep 2007) | 2 lines Refactor test failure conditions to use test.must_match(). ................ r2418 | stevenknight | 2007-09-06 14:28:52 -0500 (Thu, 06 Sep 2007) | 9 lines Restore the ability to use the Install() and InstallAs() builders without having to specify the 'install' tool directly. Add a ToolInitializer class that handles delayed intialization of tool modules when added to a construction environment as a "method." Add an env.RemoveModule() method that takes care of removing an added MethodWrapper instance from the environment, deleting it from the list that gets copied on cloning (and changing the name of that list back to "added_methods"). ................ r2419 | stevenknight | 2007-09-07 06:27:33 -0500 (Fri, 07 Sep 2007) | 3 lines Issue 1725: avoid race conditions when pushing a file to CacheDir(). (Carsten Koch) ................ r2420 | pscholl | 2007-09-07 09:13:28 -0500 (Fri, 07 Sep 2007) | 7 lines * delete the push_emitter() function. Direct manipulation of the source and target lists seem the way to go for packaging. Fix all packagers using this function. * fix the internationalization testcase ................ r2421 | pscholl | 2007-09-07 09:14:12 -0500 (Fri, 07 Sep 2007) | 3 lines * new testcase for building multiple rpm packages from one scons call. ................ r2422 | stevenknight | 2007-09-07 14:12:22 -0500 (Fri, 07 Sep 2007) | 4 lines Capture a test script with a particular reported test case for multiple Package() calls spread across different SConscript subdirectories. (Use case courtesy Andrew Smith.) ................ r2423 | stevenknight | 2007-09-07 17:40:25 -0500 (Fri, 07 Sep 2007) | 4 lines Fix use of exitstatfunc on Action objects by getting rid of the ability to override exitstatfunc when calling a function (which we were only using internally to basically suppress whatever was set on the Action object). ................ r2424 | stevenknight | 2007-09-10 20:06:59 -0500 (Mon, 10 Sep 2007) | 3 lines Make sure the library dependencies show up in --tree=derived output. (The Microsoft toolchain used to fail this on SCons 0.97 and earlier.) ................ r2425 | stevenknight | 2007-09-10 22:25:27 -0500 (Mon, 10 Sep 2007) | 5 lines When adding a new entry to a directory, reset the .implicit attribute to None so that the directory will get "re-scanned" for implicit dependencies (the entries within the directory) if it gets re-visited later in the DAG walk. ................ r2426 | stevenknight | 2007-09-12 12:38:05 -0500 (Wed, 12 Sep 2007) | 2 lines String method fix for Python 1.5.2. ................ r2427 | stevenknight | 2007-09-12 12:38:29 -0500 (Wed, 12 Sep 2007) | 2 lines Remove left-over commented-out Trace() call. ................ r2428 | stevenknight | 2007-09-13 01:36:34 -0500 (Thu, 13 Sep 2007) | 2 lines Handle Java inner class names with $ in them. (Tzvetan Mikov) ................ r2429 | stevenknight | 2007-09-13 14:29:09 -0500 (Thu, 13 Sep 2007) | 2 lines Add a check that should (possibly) avoid import errors on Solaris. ................ r2430 | stevenknight | 2007-09-13 14:30:36 -0500 (Thu, 13 Sep 2007) | 5 lines Windows portability fixes for Progress() tests, restoring the original universal_newlines setting on the test infrastructure, changing file names to make the order in which Nodes are visited case-insensitive, and fixing line endings on output we expect to read from files. ................ r2431 | stevenknight | 2007-09-14 07:58:44 -0500 (Fri, 14 Sep 2007) | 2 lines Make sure all function examples are introduced by "Example:" or "Examples:". ................ r2432 | stevenknight | 2007-09-14 11:35:03 -0500 (Fri, 14 Sep 2007) | 3 lines Clean up Options files initialization so we don't have to check on usage for whether it's been set. ................ r2433 | stevenknight | 2007-09-14 23:12:32 -0500 (Fri, 14 Sep 2007) | 4 lines Fix use of {Source,Target}Signatures() with construction variable overrides by making the default decider_*() things unbound functions, instead of bound methods. ................ r2434 | stevenknight | 2007-09-14 23:14:25 -0500 (Fri, 14 Sep 2007) | 2 lines Don't use "True" in the test infrastructure, use 1 instead. ................ r2435 | stevenknight | 2007-09-15 00:52:56 -0500 (Sat, 15 Sep 2007) | 2 lines Avoid use of False in two tests. ................ r2436 | pscholl | 2007-09-17 08:14:35 -0500 (Mon, 17 Sep 2007) | 21 lines * additional testcase for packaging: * building multiple packages from one scons call * supplying explicit target names for msi and rpm * test the Find*Files() functions * modify the package-type option test to not only catch the PACKAGETYPE, but also the --package-type alias command line argument * move FindInstalledFiles to Environment.py and remove Find*Files() functions from the packaging module. * capitalize the VENDOR tag for msi * remove the superfluous packager.py files * Add documentation for FindInstalledFiles() and FindSourceFiles() ................ r2437 | stevenknight | 2007-09-17 11:06:28 -0500 (Mon, 17 Sep 2007) | 2 lines Provide compatibility for the variables defined in SCons.Sig. ................ r2438 | stevenknight | 2007-09-17 23:13:27 -0500 (Mon, 17 Sep 2007) | 5 lines Handle duplicate fies in a target list: only decrement the reference count once for the target, not once for each time it shows up in the list, so dependencies don't "disappear" from the DAG walk because the reference count gets decremented past zero. ................ r2439 | stevenknight | 2007-09-17 23:15:45 -0500 (Mon, 17 Sep 2007) | 2 lines Fix syntax errors from failure to quote the package type. ................ r2440 | stevenknight | 2007-09-17 23:21:20 -0500 (Mon, 17 Sep 2007) | 2 lines Use AddOption() to support the --package-type option. ................ r2441 | stevenknight | 2007-09-17 23:31:40 -0500 (Mon, 17 Sep 2007) | 2 lines Skip the test if tar isn't available. ................ r2442 | stevenknight | 2007-09-18 06:35:04 -0500 (Tue, 18 Sep 2007) | 2 lines Remove Tool/packaging/packager.py from the manifest. ................ r2443 | garyo | 2007-09-18 08:13:15 -0500 (Tue, 18 Sep 2007) | 1 line SGI IRIX: use proper C++ compiler for SHCXX, don't hardcode CC. ................ r2444 | garyo | 2007-09-18 08:17:03 -0500 (Tue, 18 Sep 2007) | 1 line Avoid running MinGW tests on IRIX; they're irrelevant there and they fail anyway (they seem to pass on Linux, so left them in there.) ................ r2445 | garyo | 2007-09-18 08:20:52 -0500 (Tue, 18 Sep 2007) | 1 line Fixed wrong return type in test code; caused warnings on IRIX which made test fail. ................ r2446 | stevenknight | 2007-09-18 11:21:53 -0500 (Tue, 18 Sep 2007) | 2 lines Record Gary's change to the sgic++ tool. ................ r2451 | stevenknight | 2007-09-19 00:01:46 -0500 (Wed, 19 Sep 2007) | 2 lines Windows portability fix (when checking for path names in output). ................ r2452 | stevenknight | 2007-09-19 00:08:23 -0500 (Wed, 19 Sep 2007) | 2 lines Handle the ImportError if there's no threading module on Windows. ................
Diffstat (limited to 'test')
-rw-r--r--test/Actions/addpost-link.py22
-rw-r--r--test/Actions/exitstatfunc.py67
-rw-r--r--test/Actions/timestamp.py56
-rw-r--r--test/AddMethod.py12
-rw-r--r--test/Alias/Depends.py162
-rw-r--r--test/BuildDir/errors.py1
-rw-r--r--test/Builder/ensure_suffix.py55
-rw-r--r--test/CacheDir/multiple-targets.py66
-rw-r--r--test/CacheDir/scanner-target.py80
-rw-r--r--test/CacheDir/timestamp.py48
-rw-r--r--test/Configure/clean.py96
-rw-r--r--test/Configure/help.py109
-rw-r--r--test/Copy.py13
-rw-r--r--test/Decider/Environment.py61
-rw-r--r--test/Decider/MD5-timestamp.py81
-rw-r--r--test/Decider/Node.py61
-rw-r--r--test/Decider/default.py59
-rw-r--r--test/Decider/mixed.py115
-rw-r--r--test/Decider/timestamp.py113
-rw-r--r--test/Decider/unknown.py46
-rw-r--r--test/Delete.py20
-rw-r--r--test/Depends.py3
-rw-r--r--test/Dir/source.py4
-rw-r--r--test/Errors/preparation.py11
-rw-r--r--test/Install/Install.py22
-rw-r--r--test/Install/tool.py51
-rw-r--r--test/Java/JAVABOOTCLASSPATH.py108
-rw-r--r--test/Java/multi-step.py22
-rw-r--r--test/Java/swig-dependencies.py19
-rw-r--r--test/LIBS.py2
-rw-r--r--test/MinGW/RCCOM.py4
-rw-r--r--test/MinGW/RCCOMSTR.py4
-rw-r--r--test/NodeOps.py10
-rw-r--r--test/Parallel/duplicate-target.py74
-rw-r--r--test/Progress/TARGET.py66
-rw-r--r--test/Progress/dots.py60
-rw-r--r--test/Progress/file.py81
-rw-r--r--test/Progress/function.py75
-rw-r--r--test/Progress/interval.py68
-rw-r--r--test/Progress/object.py78
-rw-r--r--test/Progress/spinner.py66
-rw-r--r--test/QT/installed.py9
-rw-r--r--test/QT/moc-from-header.py3
-rw-r--r--test/SConscript/Return.py93
-rw-r--r--test/SWIG/build-dir.py8
-rw-r--r--test/Scanner/generated.py9
-rw-r--r--test/Sig.py62
-rw-r--r--test/SourceCode.py2
-rw-r--r--test/SourceSignatures.py268
-rw-r--r--test/SourceSignatures/basic.py124
-rw-r--r--test/SourceSignatures/env.py96
-rw-r--r--test/SourceSignatures/implicit-cache.py87
-rw-r--r--test/SourceSignatures/no-csigs.py70
-rw-r--r--test/SourceSignatures/overrides.py56
-rw-r--r--test/SourceSignatures/switch-rebuild.py81
-rw-r--r--test/TEX/auxiliaries.py13
-rw-r--r--test/TEX/clean.py94
-rw-r--r--test/TargetSignatures/build-content.py (renamed from test/TargetSignatures.py)100
-rw-r--r--test/TargetSignatures/content.py81
-rw-r--r--test/TargetSignatures/overrides.py52
-rw-r--r--test/Value.py22
-rw-r--r--test/bad-drive.py2
-rw-r--r--test/chained-build.py29
-rw-r--r--test/exceptions.py63
-rw-r--r--test/explain/get_csig.py75
-rw-r--r--test/implicit-cache/basic.py6
-rw-r--r--test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py125
-rw-r--r--test/implicit/asynchronous-modification.py89
-rw-r--r--test/implicit/changed-node.py (renamed from test/changed-node.py)0
-rw-r--r--test/option-u.py1
-rw-r--r--test/option/debug-memoizer.py1
-rw-r--r--test/option/debug-stree.py38
-rw-r--r--test/option/debug-time.py6
-rw-r--r--test/option/debug-tree.py46
-rw-r--r--test/option/taskmastertrace.py65
-rw-r--r--test/option/tree-all.py89
-rw-r--r--test/option/tree-lib.py88
-rw-r--r--test/packaging/convenience-functions.py76
-rw-r--r--test/packaging/msi/explicit-target.py92
-rw-r--r--test/packaging/multiple-packages-at-once.py82
-rw-r--r--test/packaging/multiple-subdirs.py80
-rw-r--r--test/packaging/option--package-type.py11
-rw-r--r--test/packaging/place-files-in-subdirectory.py2
-rw-r--r--test/packaging/rpm/cleanup.py8
-rw-r--r--test/packaging/rpm/explicit-target.py95
-rw-r--r--test/packaging/rpm/internationalization.py2
-rw-r--r--test/packaging/rpm/multipackage.py115
-rw-r--r--test/packaging/strip-install-dir.py5
-rw-r--r--test/question/Configure.py (renamed from test/option-q.py)101
-rw-r--r--test/question/basic.py75
-rw-r--r--test/question/no-builder.py45
-rw-r--r--test/runtest/fallback.py14
-rw-r--r--test/runtest/noqmtest.py14
-rw-r--r--test/runtest/python.py10
-rw-r--r--test/sconsign/script/Configure.py87
-rw-r--r--test/sconsign/script/SConsignFile.py362
-rw-r--r--test/sconsign/script/Signatures.py44
-rw-r--r--test/sconsign/script/dblite.py50
-rw-r--r--test/sconsign/script/no-SConsignFile.py210
-rw-r--r--test/timestamp-fallback.py14
-rw-r--r--test/up-to-date.py33
101 files changed, 5007 insertions, 844 deletions
diff --git a/test/Actions/addpost-link.py b/test/Actions/addpost-link.py
index f97d4a3..0a08cda 100644
--- a/test/Actions/addpost-link.py
+++ b/test/Actions/addpost-link.py
@@ -32,11 +32,20 @@ This is a test for fix of Issue 1004, reported by Matt Doar and
packaged by Gary Oberbrunner.
"""
+import string
+
import TestSCons
+_python_ = TestSCons._python_
test = TestSCons.TestSCons()
+test.write('strip.py', """\
+import string
+import sys
+print "strip.py: %s" % string.join(sys.argv[1:])
+""")
+
test.write('SConstruct', """\
env = Environment()
@@ -44,10 +53,12 @@ mylib = env.StaticLibrary('mytest', 'test_lib.c')
myprog = env.Program('test1.c',
LIBPATH = ['.'],
- LIBS = ['mytest'])
+ LIBS = ['mytest'],
+ OBJSUFFIX = '.obj',
+ PROGSUFFIX = '.exe')
if ARGUMENTS['case']=='2':
- AddPostAction(myprog, Action('strip ' + myprog[0].abspath))
-""")
+ AddPostAction(myprog, Action(r'%(_python_)s strip.py ' + myprog[0].abspath))
+""" % locals())
test.write('test1.c', """\
extern void test_lib_fn();
@@ -69,8 +80,11 @@ test.run(arguments="-Q case=1", stderr=None)
test.run(arguments="-Q -c case=1")
-test.must_not_exist('test1.o')
+test.must_not_exist('test1.obj')
test.run(arguments="-Q case=2", stderr=None)
+expect = 'strip.py: %s' % test.workpath('test1.exe')
+test.fail_test(string.find(test.stdout(), expect) == -1)
+
test.pass_test()
diff --git a/test/Actions/exitstatfunc.py b/test/Actions/exitstatfunc.py
new file mode 100644
index 0000000..c52e1f5
--- /dev/null
+++ b/test/Actions/exitstatfunc.py
@@ -0,0 +1,67 @@
+#!/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 setting exitstatfunc on an Action works as advertised.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+def always_succeed(s):
+ # Always return 0, which indicates success.
+ return 0
+
+def copy_fail(target, source, env):
+ content = open(str(source[0]), 'rb').read()
+ open(str(target[0]), 'wb').write(content)
+ return 2
+
+a = Action(copy_fail, exitstatfunc=always_succeed)
+Alias('test1', Command('test1.out', 'test1.in', a))
+
+def fail(target, source, env):
+ return 2
+
+t2 = Command('test2.out', 'test2.in', Copy('$TARGET', '$SOURCE'))
+AddPostAction(t2, Action(fail, exitstatfunc=always_succeed))
+Alias('test2', t2)
+""")
+
+test.write('test1.in', "test1.in\n")
+test.write('test2.in', "test2.in\n")
+
+test.run(arguments = 'test1')
+
+test.must_match('test1.out', "test1.in\n")
+
+test.run(arguments = 'test2')
+
+test.must_match('test2.out', "test2.in\n")
+
+test.pass_test()
diff --git a/test/Actions/timestamp.py b/test/Actions/timestamp.py
new file mode 100644
index 0000000..ee93596
--- /dev/null
+++ b/test/Actions/timestamp.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that changing an Action causes rebuilds when using timestamp
+signatures.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+env.Decider('timestamp-match')
+env.Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+""")
+
+test.write('file.in', "file.in\n")
+
+test.not_up_to_date(arguments = 'file.out')
+
+test.write('SConstruct', """\
+def my_copy(target, source, env):
+ open(str(target[0]), 'w').write(open(str(source[0]), 'r').read())
+env = Environment()
+env.Decider('timestamp-match')
+env.Command('file.out', 'file.in', my_copy)
+""")
+
+test.not_up_to_date(arguments = 'file.out')
+
+test.pass_test()
diff --git a/test/AddMethod.py b/test/AddMethod.py
index ef4a8d0..584ab4c 100644
--- a/test/AddMethod.py
+++ b/test/AddMethod.py
@@ -36,7 +36,7 @@ test = TestSCons.TestSCons()
test.write('SConstruct', """
def foo(self):
- return 'foo-' + env['FOO']
+ return 'foo-' + self['FOO']
AddMethod(Environment, foo)
env = Environment(FOO = '111')
@@ -46,14 +46,20 @@ env = Environment(FOO = '222')
print env.foo()
env.AddMethod(foo, 'bar')
-print env.bar()
+env['FOO'] = '333'
+
+e = env.Clone()
+e['FOO'] = '444'
+print env.bar()
+print e.bar()
""")
expect = """\
foo-111
foo-222
-foo-222
+foo-333
+foo-444
"""
test.run(arguments = '-Q -q', stdout = expect)
diff --git a/test/Alias/Depends.py b/test/Alias/Depends.py
new file mode 100644
index 0000000..b4ea95c
--- /dev/null
+++ b/test/Alias/Depends.py
@@ -0,0 +1,162 @@
+#!/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 sys
+import TestSCons
+import TestCmd
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons(match=TestCmd.match_re)
+
+test.subdir('sub1', 'sub2')
+
+test.write('build.py', r"""
+import sys
+open(sys.argv[1], 'wb').write(open(sys.argv[2], 'rb').read())
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+B = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES')
+env = Environment()
+env['BUILDERS']['B'] = B
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+env.B(target = 'f3.out', source = 'f3.in')
+SConscript('sub1/SConscript', "env")
+SConscript('sub2/SConscript', "env")
+
+foo = Alias('foo')
+foo2 = env.Alias('foo', ['f2.out', 'sub1'])
+assert foo == foo2
+bar = Alias('bar', ['sub2', 'f3.out'])
+env.Alias('blat', ['sub2', 'f3.out'])
+env.Alias('blat', ['f2.out', 'sub1'])
+env.Depends('f1.out', 'bar')
+
+Alias('a1', 'a1-file.in')
+Depends(Alias('a2'), 'a1')
+env.B('a2-file.out', 'a2-file.in')
+Depends('a2-file.out', 'a2')
+""" % locals())
+
+test.write(['sub1', 'SConscript'], """
+Import("env")
+env.B(target = 'f4.out', source = 'f4.in')
+env.B(target = 'f5.out', source = 'f5.in')
+env.B(target = 'f6.out', source = 'f6.in')
+""")
+
+test.write(['sub2', 'SConscript'], """
+Import("env")
+env.B(target = 'f7.out', source = 'f7.in')
+env.B(target = 'f8.out', source = 'f8.in')
+env.B(target = 'f9.out', source = 'f9.in')
+""")
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+test.write('f3.in', "f3.in\n")
+
+test.write(['sub1', 'f4.in'], "sub1/f4.in\n")
+test.write(['sub1', 'f5.in'], "sub1/f5.in\n")
+test.write(['sub1', 'f6.in'], "sub1/f6.in\n")
+
+test.write(['sub2', 'f7.in'], "sub2/f7.in\n")
+test.write(['sub2', 'f8.in'], "sub2/f8.in\n")
+test.write(['sub2', 'f9.in'], "sub2/f9.in\n")
+
+
+
+test.run(arguments = 'foo')
+
+test.must_not_exist(test.workpath('f1.out'))
+test.must_exist(test.workpath('f2.out'))
+test.must_not_exist(test.workpath('f3.out'))
+
+test.must_exist(test.workpath('sub1', 'f4.out'))
+test.must_exist(test.workpath('sub1', 'f5.out'))
+test.must_exist(test.workpath('sub1', 'f6.out'))
+
+test.must_not_exist(test.workpath('sub2', 'f7.out'))
+test.must_not_exist(test.workpath('sub2', 'f8.out'))
+test.must_not_exist(test.workpath('sub2', 'f9.out'))
+
+test.up_to_date(arguments = 'foo')
+
+test.write(['sub1', 'f5.in'], "sub1/f5.in 2\n")
+
+test.not_up_to_date(arguments = 'foo')
+
+
+
+test.run(arguments = 'f1.out')
+
+test.must_exist(test.workpath('f1.out'))
+test.must_exist(test.workpath('f3.out'))
+
+test.up_to_date(arguments = 'f1.out')
+
+
+
+os.unlink(test.workpath('f2.out'))
+os.unlink(test.workpath('f3.out'))
+
+test.run(arguments = 'blat')
+
+test.must_exist(test.workpath('f2.out'))
+test.must_exist(test.workpath('f3.out'))
+
+test.write('f3.in', "f3.in 2 \n")
+
+expect = """.* build.py f3.out f3.in
+.* build.py f1.out f1.in
+"""
+
+test.run(arguments = '-Q f1.out', stdout = expect)
+
+test.up_to_date(arguments = 'f1.out')
+
+
+
+test.write('a1-file.in', "a1-file.in\n")
+test.write('a2-file.in', "a2-file.in\n")
+
+test.run(arguments = 'a2-file.out')
+
+test.must_match(test.workpath('a2-file.out'), "a2-file.in\n")
+
+test.up_to_date(arguments = 'a2-file.out')
+
+test.write('a1-file.in', "a1-file.in 2\n")
+
+test.not_up_to_date(arguments = 'a2-file.out')
+
+
+
+test.pass_test()
diff --git a/test/BuildDir/errors.py b/test/BuildDir/errors.py
index 44096a1..3954f2b 100644
--- a/test/BuildDir/errors.py
+++ b/test/BuildDir/errors.py
@@ -70,7 +70,6 @@ env = Environment(BUILDERS={'Build':Builder(action=cat)},
# Do some Node test operations to ensure no side-effects cause failures
File('file.in').exists()
File('file.in').is_derived()
-File('file.in').is_pseudo_derived()
env.Build('file.out', 'file.in')
""")
diff --git a/test/Builder/ensure_suffix.py b/test/Builder/ensure_suffix.py
new file mode 100644
index 0000000..ee23635
--- /dev/null
+++ b/test/Builder/ensure_suffix.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the ensure_suffix argument to causes us to add the suffix
+configured for the Builder even if it looks like the target already has
+a different suffix.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+
+tbuilder = Builder(action=Copy('$TARGET', '$SOURCE'),
+ suffix='.dll',
+ ensure_suffix=True)
+
+env['BUILDERS']['TBuilder'] = tbuilder
+
+env.TBuilder("aa.bb.cc.dd","aa.aa.txt")
+""")
+
+test.write('aa.aa.txt', "clean test\n")
+
+test.run(arguments = '.')
+
+test.must_match('aa.bb.cc.dd.dll', "clean test\n")
+
+test.pass_test()
diff --git a/test/CacheDir/multiple-targets.py b/test/CacheDir/multiple-targets.py
new file mode 100644
index 0000000..77b8f6f
--- /dev/null
+++ b/test/CacheDir/multiple-targets.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__"
+
+"""
+Test that multiple target files get retrieved from a CacheDir correctly.
+"""
+
+import os.path
+import shutil
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('cache')
+
+test.write('SConstruct', """\
+def touch(env, source, target):
+ open('foo', 'w').write("")
+ open('bar', 'w').write("")
+CacheDir(r'%s')
+env = Environment()
+env.Command(['foo', 'bar'], ['input'], touch)
+""" % (test.workpath('cache')))
+
+test.write('input', "multiple/input\n")
+
+test.run()
+
+test.must_exist(test.workpath('foo'))
+test.must_exist(test.workpath('bar'))
+
+test.run(arguments = '-c')
+
+test.must_not_exist(test.workpath('foo'))
+test.must_not_exist(test.workpath('bar'))
+
+test.run()
+
+test.must_exist(test.workpath('foo'))
+test.must_exist(test.workpath('bar'))
+
+test.pass_test()
diff --git a/test/CacheDir/scanner-target.py b/test/CacheDir/scanner-target.py
new file mode 100644
index 0000000..33930d8
--- /dev/null
+++ b/test/CacheDir/scanner-target.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the case (reported by Jeff Petkau, bug #694744) where a target
+is source for another target with a scanner, which used to cause us
+to push the file to the CacheDir after the build signature had already
+been cleared (as a sign that the built file should now be rescanned).
+"""
+
+import os.path
+import shutil
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('cache')
+
+test.write('SConstruct', """\
+import SCons
+
+CacheDir(r'%s')
+
+def docopy(target,source,env):
+ data = source[0].get_contents()
+ f = open(target[0].rfile().get_abspath(), "wb")
+ f.write(data)
+ f.close()
+
+def sillyScanner(node, env, dirs):
+ print 'This is never called (unless we build file.out)'
+ return []
+
+SillyScanner = SCons.Scanner.Base(function = sillyScanner, skeys = ['.res'])
+
+env = Environment(tools=[],
+ SCANNERS = [SillyScanner],
+ BUILDERS = {})
+
+r = env.Command('file.res', 'file.ma', docopy)
+
+env.Command('file.out', r, docopy)
+
+# make r the default. Note that we don't even try to build file.out,
+# and so SillyScanner never runs. The bug is the same if we build
+# file.out, though.
+Default(r)
+""" % test.workpath('cache'))
+
+test.write('file.ma', "file.ma\n")
+
+test.run()
+
+test.must_not_exist(test.workpath('cache', 'N', 'None'))
+
+test.pass_test()
diff --git a/test/CacheDir/timestamp.py b/test/CacheDir/timestamp.py
new file mode 100644
index 0000000..b0d45b6
--- /dev/null
+++ b/test/CacheDir/timestamp.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that CacheDir() works even when using timestamp signatures.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+SourceSignatures('timestamp')
+TargetSignatures('content')
+CacheDir('cache')
+Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run()
+
+test.must_match('file.out', "file.in\n")
+
+test.pass_test()
diff --git a/test/Configure/clean.py b/test/Configure/clean.py
new file mode 100644
index 0000000..5b8e43d
--- /dev/null
+++ b/test/Configure/clean.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 don't perform Configure context actions when the
+-c or --clean options have been specified.
+"""
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+env = Environment()
+import os
+env.AppendENVPath('PATH', os.environ['PATH'])
+conf = Configure(env)
+r1 = conf.CheckCHeader( 'math.h' )
+r2 = conf.CheckCHeader( 'no_std_c_header.h' ) # leads to compile error
+env = conf.Finish()
+Export( 'env' )
+SConscript( 'SConscript' )
+""")
+
+test.write('SConscript', """\
+Import( 'env' )
+env.Program( 'TestProgram', 'TestProgram.c' )
+""")
+
+test.write('TestProgram.c', """\
+#include <stdio.h>
+
+int main() {
+ printf( "Hello\\n" );
+}
+""")
+
+lines = [
+ "Checking for C header file math.h... ",
+ "Checking for C header file no_std_c_header.h... "
+]
+
+unexpected = []
+
+test.run(arguments = '-c')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.run(arguments = '--clean')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.pass_test()
diff --git a/test/Configure/help.py b/test/Configure/help.py
new file mode 100644
index 0000000..f79831c
--- /dev/null
+++ b/test/Configure/help.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that we don't perform Configure context actions when the
+-H, -h or --help options have been specified.
+"""
+
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+env = Environment()
+import os
+env.AppendENVPath('PATH', os.environ['PATH'])
+conf = Configure(env)
+r1 = conf.CheckCHeader( 'math.h' )
+r2 = conf.CheckCHeader( 'no_std_c_header.h' ) # leads to compile error
+env = conf.Finish()
+Export( 'env' )
+SConscript( 'SConscript' )
+""")
+
+test.write('SConscript', """\
+Import( 'env' )
+env.Program( 'TestProgram', 'TestProgram.c' )
+""")
+
+test.write('TestProgram.c', """\
+#include <stdio.h>
+
+int main() {
+ printf( "Hello\\n" );
+}
+""")
+
+lines = [
+ "Checking for C header file math.h... ",
+ "Checking for C header file no_std_c_header.h... "
+]
+
+unexpected = []
+
+test.run(arguments = '-H')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.run(arguments = '-h')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.run(arguments = '--help')
+
+for line in lines:
+ if string.find(test.stdout(), line) != -1:
+ unexpected.append(line)
+
+if unexpected:
+ print "Unexpected lines in standard output:"
+ print string.join(unexpected, '\n')
+ print "STDOUT ============================================================"
+ print test.stdout()
+ test.fail_test()
+
+test.pass_test()
diff --git a/test/Copy.py b/test/Copy.py
index 4da725e..6659d93 100644
--- a/test/Copy.py
+++ b/test/Copy.py
@@ -79,6 +79,11 @@ test.write('f11.in', "f11.in\n")
test.subdir('d5')
test.write(['d5', 'f12.in'], "f12.in\n")
+d4_f10_in = os.path.join('d4', 'f10.in')
+d4_f11_out = os.path.join('d4', 'f11.out')
+d4_f12_out = os.path.join('d4', 'f12.out')
+d5_f12_in = os.path.join('d5', 'f12.in')
+
expect = test.wrap_stdout(read_str = """\
Copy("f1.out", "f1.in")
Copy("d2.out", "d2.in")
@@ -89,14 +94,14 @@ cat(["bar.out"], ["bar.in"])
Copy("f4.out", "f4.in")
Copy("d5.out", "d5.in")
Copy("d6.out", "f6.in")
-Copy file(s): "f10.in" to "d4/f10.in"
-Copy file(s): "f11.in" to "d4/f11.out"
-Copy file(s): "d5/f12.in" to "d4/f12.out"
+Copy file(s): "f10.in" to "%(d4_f10_in)s"
+Copy file(s): "f11.in" to "%(d4_f11_out)s"
+Copy file(s): "%(d5_f12_in)s" to "%(d4_f12_out)s"
Copy("f7.out", "f7.in")
cat(["f8.out"], ["f8.in"])
cat(["f9.out"], ["f9.in"])
Copy("f9.out-Copy", "f9.in")
-""")
+""" % locals())
test.run(options = '-n', arguments = '.', stdout = expect)
test.must_not_exist('f1.out')
diff --git a/test/Decider/Environment.py b/test/Decider/Environment.py
new file mode 100644
index 0000000..989e187
--- /dev/null
+++ b/test/Decider/Environment.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify use of an up-to-date Decider method through a construction
+environment.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import os.path
+env = Environment()
+env.Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+def my_decider(dependency, target, prev_ni):
+ return os.path.exists('has-changed')
+env.Decider(my_decider)
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+test.write('has-changed', "\n")
+
+test.not_up_to_date(arguments = '.')
+
+test.not_up_to_date(arguments = '.')
+
+test.unlink('has-changed')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Decider/MD5-timestamp.py b/test/Decider/MD5-timestamp.py
new file mode 100644
index 0000000..d31a2db
--- /dev/null
+++ b/test/Decider/MD5-timestamp.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 behavior of the MD5-timestamp Decider() setting.
+"""
+
+import os
+import stat
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+m = Environment()
+m.Decider('MD5-timestamp')
+m.Command('content1.out', 'content1.in', Copy('$TARGET', '$SOURCE'))
+m.Command('content2.out', 'content2.in', Copy('$TARGET', '$SOURCE'))
+m.Command('content3.out', 'content3.in', Copy('$TARGET', '$SOURCE'))
+""")
+
+test.write('content1.in', "content1.in 1\n")
+test.write('content2.in', "content2.in 1\n")
+test.write('content3.in', "content3.in 1\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+
+
+test.sleep()
+
+test.write('content1.in', "content1.in 2\n")
+
+test.touch('content2.in')
+
+time_content = os.stat('content3.in')[stat.ST_MTIME]
+test.write('content3.in', "content3.in 2\n")
+test.touch('content3.in', time_content)
+
+# We should only see content1.out rebuilt. The timestamp of content2.in
+# has changed, but its content hasn't, so the follow-on content check says
+# to not rebuild it. The content of content3.in has changed, but that's
+# masked by the fact that its timestamp is the same as the last run.
+
+expect = test.wrap_stdout("""\
+Copy("content1.out", "content1.in")
+""")
+
+test.run(arguments = '.', stdout=expect)
+
+test.up_to_date(arguments = '.')
+
+
+
+test.pass_test()
diff --git a/test/Decider/Node.py b/test/Decider/Node.py
new file mode 100644
index 0000000..b11e223
--- /dev/null
+++ b/test/Decider/Node.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify use of an up-to-date Decider method on a Node.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import os.path
+file_in = File('file.in')
+file_out = File('file.out')
+Command(file_out, file_in, Copy('$TARGET', '$SOURCE'))
+def my_decider(dependency, target, prev_ni):
+ return os.path.exists('has-changed')
+file_in.Decider(my_decider)
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+test.write('has-changed', "\n")
+
+test.not_up_to_date(arguments = '.')
+
+test.not_up_to_date(arguments = '.')
+
+test.unlink('has-changed')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Decider/default.py b/test/Decider/default.py
new file mode 100644
index 0000000..c2886fb
--- /dev/null
+++ b/test/Decider/default.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify use of a default up-to-date Decider method.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import os.path
+Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+def my_decider(dependency, target, prev_ni):
+ return os.path.exists('has-changed')
+Decider(my_decider)
+""")
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+test.write('has-changed', "\n")
+
+test.not_up_to_date(arguments = '.')
+
+test.not_up_to_date(arguments = '.')
+
+test.unlink('has-changed')
+
+test.up_to_date(arguments = '.')
+
+test.pass_test()
diff --git a/test/Decider/mixed.py b/test/Decider/mixed.py
new file mode 100644
index 0000000..7a83c74
--- /dev/null
+++ b/test/Decider/mixed.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 use of an up-to-date Decider method through a construction
+environment.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import os.path
+denv = Environment()
+env = Environment()
+n1_in = File('n1.in')
+n2_in = File('n2.in')
+n3_in = File('n3.in')
+Command( 'ccc.out', 'ccc.in', Copy('$TARGET', '$SOURCE'))
+Command( 'n1.out', n1_in, Copy('$TARGET', '$SOURCE'))
+denv.Command('ddd.out', 'ddd.in', Copy('$TARGET', '$SOURCE'))
+denv.Command('n2.out', n2_in, Copy('$TARGET', '$SOURCE'))
+env.Command( 'eee.out', 'eee.in', Copy('$TARGET', '$SOURCE'))
+env.Command( 'n3.out', n3_in, Copy('$TARGET', '$SOURCE'))
+def default_decider(dependency, target, prev_ni):
+ return os.path.exists('default-has-changed')
+def env_decider(dependency, target, prev_ni):
+ return os.path.exists('env-has-changed')
+def node_decider(dependency, target, prev_ni):
+ return os.path.exists('node-has-changed')
+Decider(default_decider)
+env.Decider(env_decider)
+n1_in.Decider(node_decider)
+n2_in.Decider(node_decider)
+n3_in.Decider(node_decider)
+""")
+
+test.write('ccc.in', "ccc.in\n")
+test.write('ddd.in', "ddd.in\n")
+test.write('eee.in', "eee.in\n")
+test.write('n1.in', "n1.in\n")
+test.write('n2.in', "n2.in\n")
+test.write('n3.in', "n3.in\n")
+
+
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+
+
+test.write('env-has-changed', "\n")
+
+test.not_up_to_date(arguments = 'eee.out')
+test.up_to_date(arguments = 'ccc.out ddd.out n1.out n2.out n3.out')
+
+test.not_up_to_date(arguments = 'eee.out')
+test.up_to_date(arguments = 'ccc.out ddd.out n1.out n2.out n3.out')
+
+test.unlink('env-has-changed')
+
+
+
+test.write('default-has-changed', "\n")
+
+test.not_up_to_date(arguments = 'ccc.out ddd.out')
+test.up_to_date(arguments = 'eee.out n1.out n2.out n3.out')
+
+test.not_up_to_date(arguments = 'ccc.out ddd.out')
+test.up_to_date(arguments = 'eee.out n1.out n2.out n3.out')
+
+test.unlink('default-has-changed')
+
+
+
+test.up_to_date(arguments = '.')
+
+test.write('node-has-changed', "\n")
+
+test.not_up_to_date(arguments = 'n1.out n2.out n3.out')
+test.up_to_date(arguments = 'ccc.out ddd.out eee.out')
+
+test.not_up_to_date(arguments = 'n1.out n2.out n3.out')
+test.up_to_date(arguments = 'ccc.out ddd.out eee.out')
+
+test.unlink('node-has-changed')
+
+
+
+test.pass_test()
diff --git a/test/Decider/timestamp.py b/test/Decider/timestamp.py
new file mode 100644
index 0000000..6975607
--- /dev/null
+++ b/test/Decider/timestamp.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 various interactions of the timestamp-match and timestamp-newer
+Decider() settings:.
+"""
+
+import os
+import stat
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+m = Environment()
+m.Decider('timestamp-match')
+m.Command('match1.out', 'match1.in', Copy('$TARGET', '$SOURCE'))
+m.Command('match2.out', 'match2.in', Copy('$TARGET', '$SOURCE'))
+n = Environment()
+n.Decider('timestamp-newer')
+n.Command('newer1.out', 'newer1.in', Copy('$TARGET', '$SOURCE'))
+n.Command('newer2.out', 'newer2.in', Copy('$TARGET', '$SOURCE'))
+""")
+
+test.write('match1.in', "match1.in\n")
+test.write('match2.in', "match2.in\n")
+test.write('newer1.in', "newer1.in\n")
+test.write('newer2.in', "newer2.in\n")
+
+test.run(arguments = '.')
+
+test.up_to_date(arguments = '.')
+
+time_match = os.stat('match2.out')[stat.ST_MTIME]
+time_newer = os.stat('newer2.out')[stat.ST_MTIME]
+
+
+
+# Now make all the source files newer than (different timestamps from)
+# the last time the targets were built, and touch the target files
+# of match1.out and newer1.out to see the different effects.
+
+test.sleep()
+
+test.touch('match1.in')
+test.touch('newer1.in')
+test.touch('match2.in')
+test.touch('newer2.in')
+
+test.sleep()
+
+test.touch('match1.out')
+test.touch('newer1.out')
+
+# We should see both match1.out and match2.out rebuilt, because the
+# source file timestamps do not match the last time they were built,
+# but only newer2.out rebuilt. newer1.out is *not* rebuilt because
+# the actual target file timestamp is, in fact, newer than the
+# source file (newer1.in) timestamp.
+
+expect = test.wrap_stdout("""\
+Copy("match1.out", "match1.in")
+Copy("match2.out", "match2.in")
+Copy("newer2.out", "newer2.in")
+""")
+
+test.run(arguments = '.', stdout=expect)
+
+# Now, for the somewhat pathological case, reset the match2.out and
+# newer2.out timestamps to the older timestamp when the targets were
+# first built. This will cause newer2.out to be rebuilt, because
+# the newer1.in timestamp is now newer than the older, reset target
+# file timestamp, but match2.out is *not* rebuilt because its source
+# file (match2.in) timestamp still exactly matches the timestamp
+# recorded when the target file was last built.
+
+test.touch('match2.out', time_match)
+test.touch('newer2.out', time_newer)
+
+expect = test.wrap_stdout("""\
+Copy("newer2.out", "newer2.in")
+""")
+
+test.run(arguments = '.', stdout=expect)
+
+
+
+test.pass_test()
diff --git a/test/Decider/unknown.py b/test/Decider/unknown.py
new file mode 100644
index 0000000..b6d071d
--- /dev/null
+++ b/test/Decider/unknown.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify the error when the Decider() function is handed an unknown
+function string.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+
+test.write('SConstruct', """\
+Decider('fiddle-dee-dee')
+""")
+
+expect = r"""
+scons: \*\*\* Unknown Decider value 'fiddle-dee-dee'
+""" + TestSCons.file_expr
+
+test.run(arguments = '.', status = 2, stderr = expect)
+
+test.pass_test()
diff --git a/test/Delete.py b/test/Delete.py
index 138dc95..31febbe 100644
--- a/test/Delete.py
+++ b/test/Delete.py
@@ -53,14 +53,18 @@ env.Command('f8.out', 'f8.in', [Delete("$FILE"), Delete("$DIR"), Cat])
env.Command('f9.out', 'f9.in', [Cat,
Delete("Delete-$SOURCE"),
Delete("$TARGET-Delete")])
-env.Command('f10-nonexistent.out', 'f10.in', [Delete("$TARGET"),
- Cat])
-env.Command('d11-nonexistent.out', 'd11.in', [Delete("$TARGET"),
- Mkdir("$TARGET")])
-env.Command('f12-nonexistent.out', 'f12.in', [Delete("$TARGET", must_exist=0),
- Cat])
-env.Command('d13-nonexistent.out', 'd13.in', [Delete("$TARGET", must_exist=0),
- Mkdir("$TARGET")])
+
+env.Command('f10-nonexistent.out', 'f10.in',
+ [Delete("$TARGET"), Cat])
+
+env.Command(Dir('d11-nonexistent.out'), 'd11.in',
+ [Delete("$TARGET"), Mkdir("$TARGET")])
+
+env.Command('f12-nonexistent.out', 'f12.in',
+ [Delete("$TARGET", must_exist=0), Cat])
+
+env.Command(Dir('d13-nonexistent.out'), 'd13.in',
+ [Delete("$TARGET", must_exist=0), Mkdir("$TARGET")])
""")
test.write('f1', "f1\n")
diff --git a/test/Depends.py b/test/Depends.py
index d0b2199..4870739 100644
--- a/test/Depends.py
+++ b/test/Depends.py
@@ -143,6 +143,9 @@ file2 = File('file2')
env.Depends(file1, [[file2, 'file3']])
""")
+test.write('file2', "file2\n")
+test.write('file3', "file3\n")
+
test.up_to_date(arguments = '.')
test.pass_test()
diff --git a/test/Dir/source.py b/test/Dir/source.py
index fa07a88..9852660 100644
--- a/test/Dir/source.py
+++ b/test/Dir/source.py
@@ -165,8 +165,6 @@ test.up_to_date(arguments='cmd-csig-noscan.out')
test.write('junk.txt', 'junk.txt 2\n')
test.not_up_to_date(arguments='bsig.out')
-# XXX For some reason, 'csig' is still reported as up to date.
-# XXX Comment out this test until someone can look at it.
-#test.not_up_to_date(arguments='csig.out')
+test.not_up_to_date(arguments='csig.out')
test.pass_test()
diff --git a/test/Errors/preparation.py b/test/Errors/preparation.py
index 3f98894..9857f99 100644
--- a/test/Errors/preparation.py
+++ b/test/Errors/preparation.py
@@ -35,19 +35,18 @@ import TestSCons
test = TestSCons.TestSCons()
-install = test.workpath('install')
-install_file = test.workpath('install', 'file')
-work_file = test.workpath('work', 'file')
+work_file_out = test.workpath('work', 'file.out')
test.subdir('install', 'work')
test.write(['work', 'SConstruct'], """\
-Alias("install", Install(r"%(install)s", File('file')))
+file_out = Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE'))
+Alias("install", file_out)
# Make a directory where we expect the File() to be. This causes an
# IOError or OSError when we try to open it to read its signature.
import os
-os.mkdir(r'%(work_file)s')
+os.mkdir('file.in')
""" % locals())
if sys.platform == 'win32':
@@ -56,7 +55,7 @@ else:
error_message = "Is a directory"
expect = """\
-scons: *** [%(install_file)s] %(work_file)s: %(error_message)s
+scons: *** [install] %(work_file_out)s: %(error_message)s
""" % locals()
test.run(chdir = 'work',
diff --git a/test/Install/Install.py b/test/Install/Install.py
index f7f8e26..6d44c45 100644
--- a/test/Install/Install.py
+++ b/test/Install/Install.py
@@ -91,18 +91,18 @@ test.write(['work', 'sub', 'f4.in'], "sub/f4.in\n")
test.write(f5_txt, "f5.txt\n")
test.write(f6_txt, "f6.txt\n")
-test.run(chdir = 'work', arguments = '--debug=stacktrace .')
+test.run(chdir = 'work', arguments = '.')
-test.fail_test(test.read(f1_out) != "f1.in\n")
-test.fail_test(test.read(f2_out) != "f2.in\n")
-test.fail_test(test.read(f3_out) != "f3.in\n")
-test.fail_test(test.read(f4_out) != "sub/f4.in\n")
-test.fail_test(test.read(['work', 'f5.txt']) != "f5.txt\n")
-test.fail_test(test.read(['work', 'export', 'f5.txt']) != "f5.txt\n")
-test.fail_test(test.read(['work', 'f6.txt']) != "f6.txt\n")
-test.fail_test(test.read(['work', 'export', 'f6.txt']) != "f6.txt\n")
+test.must_match(f1_out, "f1.in\n")
+test.must_match(f2_out, "f2.in\n")
+test.must_match(f3_out, "f3.in\n")
+test.must_match(f4_out, "sub/f4.in\n")
+test.must_match(['work', 'f5.txt'], "f5.txt\n")
+test.must_match(['work', 'export', 'f5.txt'], "f5.txt\n")
+test.must_match(['work', 'f6.txt'], "f6.txt\n")
+test.must_match(['work', 'export', 'f6.txt'], "f6.txt\n")
-test.fail_test(test.read(['work', 'my_install.out']) != os.path.join('export', 'f3.out'))
+test.must_match(['work', 'my_install.out'], os.path.join('export', 'f3.out'))
# make sure the programs didn't get rebuilt, because nothing changed:
oldtime1 = os.path.getmtime(f1_out)
@@ -119,7 +119,7 @@ test.fail_test(oldtime2 != os.path.getmtime(f2_out))
# Verify that we didn't link to the Installed file.
open(f2_out, 'wb').write("xyzzy\n")
-test.fail_test(test.read(['work', 'f2.out']) != "f2.in\n")
+test.must_match(['work', 'f2.out'], "f2.in\n")
# Verify that scons prints an error message
# if a target can not be unlinked before building it:
diff --git a/test/Install/tool.py b/test/Install/tool.py
new file mode 100644
index 0000000..4f09b73
--- /dev/null
+++ b/test/Install/tool.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that we can still call Install() and InstallAs() even when
+no Tool modules have been loaded.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.subdir('iii')
+
+test.write('SConstruct', """
+env = Environment(tools = [])
+env.Install('iii', 'foo.in')
+env.InstallAs('foo.out', 'foo.in')
+""")
+
+test.write('foo.in', "foo.in\n")
+
+test.run(arguments = '.')
+
+test.must_match(['iii', 'foo.in'], "foo.in\n")
+test.must_match('foo.out', "foo.in\n")
+
+test.pass_test()
diff --git a/test/Java/JAVABOOTCLASSPATH.py b/test/Java/JAVABOOTCLASSPATH.py
new file mode 100644
index 0000000..7723224
--- /dev/null
+++ b/test/Java/JAVABOOTCLASSPATH.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 use of $JAVABOOTCLASSPATH sets the -bootclasspath option
+on javac compilations.
+"""
+
+import os
+import string
+
+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('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")
+
+test.write('SConstruct', """
+env = Environment(tools = ['javac', 'javah'],
+ JAVAC = r'%(where_javac)s',
+ JAVABOOTCLASSPATH = ['dir1', 'dir2'])
+j1 = env.Java(target = 'class', source = 'com/Example1.java')
+j2 = env.Java(target = 'class', source = 'com/Example2.java')
+""" % locals())
+
+test.subdir('com')
+
+test.write(['com', 'Example1.java'], """\
+package com;
+
+public class Example1
+{
+
+ public static void main(String[] args)
+ {
+
+ }
+
+}
+""")
+
+test.write(['com', 'Example2.java'], """\
+package com;
+
+public class Example2
+{
+
+ public static void main(String[] args)
+ {
+
+ }
+
+}
+""")
+
+# Setting -bootclasspath messes with the Java runtime environment, so
+# we'll just take the easy way out and examine the -n output to see if
+# the expected option shows up on the command line.
+
+bootclasspath = string.join(['dir1', 'dir2'], os.pathsep)
+
+expect = """\
+%(where_javac)s -bootclasspath %(bootclasspath)s -d class -sourcepath com com/Example1.java
+%(where_javac)s -bootclasspath %(bootclasspath)s -d class -sourcepath com com/Example2.java
+""" % locals()
+
+test.run(arguments = '-Q -n .', stdout = expect)
+
+test.pass_test()
diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py
index 1b69838..d185b4d 100644
--- a/test/Java/multi-step.py
+++ b/test/Java/multi-step.py
@@ -43,6 +43,13 @@ else:
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")
+
swig = test.where_is('swig')
if not swig:
test.skip_test('Can not find installed "swig", skipping test.\n')
@@ -70,7 +77,9 @@ test.subdir(['src'],
test.write(['SConstruct'], """\
import os,sys
-env=Environment(tools = ['default', 'javac', 'javah'])
+env=Environment(tools = ['default', 'javac', 'javah'],
+ JAVAC = r'%(where_javac)s',
+ JAVAH = r'%(where_javah)s')
Export('env')
env.PrependENVPath('PATH',os.environ.get('PATH',[]))
env['INCPREFIX']='-I'
@@ -94,7 +103,7 @@ env.SConscript(['buildout/server/JavaSource/SConscript',
'buildout/HelloApplet/SConscript',
'buildout/jni/SConscript',
'buildout/javah/SConscript'])
-""")
+""" % locals())
test.write(['src', 'HelloApplet', 'Hello.html'], """\
<HTML>
@@ -559,9 +568,16 @@ test.must_exist(['buildout', 'jni', 'Sample.class'])
test.must_exist(['buildout', 'jni', 'Sample.java'])
test.must_exist(['buildout', 'jni', 'SampleJNI.class'])
test.must_exist(['buildout', 'jni', 'SampleJNI.java'])
-test.must_exist(['buildout', 'jni', 'SampleTest.class'])
test.must_exist(['buildout', 'jni', 'SampleTest.java'])
+# Some combinations of Java + SWIG apparently don't actually generate
+# a SampleTest.class file, while others do. Only issue a warning if
+# it doesn't exist.
+p = test.workpath('buildout', 'jni', 'SampleTest.class')
+import os.path
+if not os.path.exists(p):
+ print 'Warning: %s does not exist' % p
+
test.up_to_date(arguments = '.')
test.pass_test()
diff --git a/test/Java/swig-dependencies.py b/test/Java/swig-dependencies.py
index c6961f2..8df5e09 100644
--- a/test/Java/swig-dependencies.py
+++ b/test/Java/swig-dependencies.py
@@ -35,6 +35,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:
@@ -42,6 +43,13 @@ else:
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:
@@ -57,7 +65,9 @@ test.subdir(['foo'],
test.write(['SConstruct'], """\
import os
-env = Environment(ENV = os.environ)
+env = Environment(ENV = os.environ,
+ JAVAC = r'%(where_javac)s',
+ JAVAH = r'%(where_javah)s')
env.Append(CPPFLAGS = ' -g -Wall')
@@ -65,7 +75,7 @@ Export('env')
SConscript('#foo/SConscript')
SConscript('#java/SConscript')
-""")
+""" % locals())
test.write(['foo', 'SConscript'], """\
Import('env')
@@ -123,7 +133,10 @@ env['JARCHDIR'] = 'java/classes'
foopack_jar = env.Jar(target = 'foopack.jar', source = 'classes')
""")
-test.run(arguments = '.')
+# Disable looking at stderr because some combinations of SWIG/gcc
+# generate a warning about the sWIG_JavaThrowException() function
+# being defined but not used.
+test.run(arguments = '.', stderr=None)
#test.must_exist(['java', 'classes', 'foopack', 'foopack.class'])
#test.must_exist(['java', 'classes', 'foopack', 'foopackJNI.class'])
diff --git a/test/LIBS.py b/test/LIBS.py
index 708ce63..e9f6545 100644
--- a/test/LIBS.py
+++ b/test/LIBS.py
@@ -272,7 +272,7 @@ test.write(['src', 'component2', 'message2.c'], """\
#include <stdio.h>
#include "message1.h"
-int DisplayMessage2 (void)
+void DisplayMessage2 (void)
{
DisplayMessage1();
printf ("src/component2/hello.c\\n");
diff --git a/test/MinGW/RCCOM.py b/test/MinGW/RCCOM.py
index 2db0563..a272af7 100644
--- a/test/MinGW/RCCOM.py
+++ b/test/MinGW/RCCOM.py
@@ -29,13 +29,15 @@ Test the ability to configure the $RCCOM construction variable
when using MinGW.
"""
+import sys
import TestSCons
_python_ = TestSCons._python_
test = TestSCons.TestSCons()
-
+if sys.platform in ('irix6',):
+ test.skip_test("Skipping mingw test on non-Windows %s platform."%sys.platform)
test.write('myrc.py', """
import sys
diff --git a/test/MinGW/RCCOMSTR.py b/test/MinGW/RCCOMSTR.py
index 96565f1..d04c5d6 100644
--- a/test/MinGW/RCCOMSTR.py
+++ b/test/MinGW/RCCOMSTR.py
@@ -29,13 +29,15 @@ Test that the $RCCOMSTR construction variable allows you to customize
the displayed string when rc is called.
"""
+import sys
import TestSCons
_python_ = TestSCons._python_
test = TestSCons.TestSCons()
-
+if sys.platform in ('irix6',):
+ test.skip_test("Skipping mingw test on non-Windows %s platform."%sys.platform)
test.write('myrc.py', """
import sys
diff --git a/test/NodeOps.py b/test/NodeOps.py
index 3869228..7e656f7 100644
--- a/test/NodeOps.py
+++ b/test/NodeOps.py
@@ -32,9 +32,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
# However, this should *not* occur during a dryrun (-n). When not
# performed during a dryrun, this should not affect buildability.
# 2) Calling is_derived() should not affect buildability.
-# 3) Calling is_pseudo_derived() may cause the sbuilder to be set, and
-# it may caues the builder to be set as well, but it should not
-# adversely affect buildability.
import sys
import TestSCons
@@ -73,13 +70,11 @@ SConscript('bld/SConscript', ['Nodes'])
if %(_E)s:
import os
derived = map(lambda N: N.is_derived(), Nodes)
- p_derived = map(lambda N: N.is_pseudo_derived(), Nodes)
real1 = map(lambda N: os.path.exists(str(N)), Nodes)
exists = map(lambda N: N.exists(), Nodes)
real2 = map(lambda N: os.path.exists(str(N)), Nodes)
- for N,D,P,R,E,F in map(None, Nodes, derived, p_derived,
- real1, exists, real2):
- print '%%s: %%s %%s %%s %%s %%s'%%(N,D,P,R,E,F)
+ for N,D,R,E,F in map(None, Nodes, derived, real1, exists, real2):
+ print '%%s: %%s %%s %%s %%s'%%(N,D,R,E,F)
foo.SharedLibrary(target = 'foo', source = 'foo%(_obj)s')
bar.SharedLibrary(target = 'bar', source = 'bar%(_obj)s')
@@ -147,7 +142,6 @@ def exists_test(node):
via_node = node.exists() # side effect causes copy from src
after = os.path.exists(str(node))
node.is_derived()
- node.is_pseudo_derived()
import SCons.Script
if GetOption('no_exec'):
if (before,via_node,after) != (False,False,False):
diff --git a/test/Parallel/duplicate-target.py b/test/Parallel/duplicate-target.py
new file mode 100644
index 0000000..5d4f5e1
--- /dev/null
+++ b/test/Parallel/duplicate-target.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that, when a file is specified multiple times in a target
+list, we still build all of the necessary targets.
+
+This used to cause a target to "disappear" from the DAG when its reference
+count dropped below 0, because we were subtracting the duplicated target
+mutiple times even though we'd only visit it once. This was particularly
+hard to track down because the DAG itself (when printed with --tree=prune,
+for example) doesn't show the duplication in the *target* list.
+"""
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+test.subdir('work')
+
+tar_output = test.workpath('work.tar')
+
+test.write(['work', 'copy.py'], """\
+import sys
+import time
+time.sleep(int(sys.argv[1]))
+open(sys.argv[2], 'wb').write(open(sys.argv[3], 'rb').read())
+""")
+
+test.write(['work', 'SConstruct'], """\
+env = Environment()
+out1 = File('f1.out')
+out2 = File('f2.out')
+env.Command([out1, out1], 'f1.in', r'%(_python_)s copy.py 3 $TARGET $SOURCE')
+env.Command([out2, out2], 'f2.in', r'%(_python_)s copy.py 3 $TARGET $SOURCE')
+
+env.Tar(r'%(tar_output)s', Dir('.'))
+""" % locals())
+
+test.write(['work', 'f1.in'], "work/f1.in\n")
+test.write(['work', 'f2.in'], "work/f2.in\n")
+
+test.run(chdir = 'work', arguments = tar_output + ' -j2')
+
+test.must_match(['work', 'f1.out'], "work/f1.in\n")
+test.must_match(['work', 'f2.out'], "work/f2.in\n")
+test.must_exist(tar_output)
+
+test.pass_test()
diff --git a/test/Progress/TARGET.py b/test/Progress/TARGET.py
new file mode 100644
index 0000000..e45f859
--- /dev/null
+++ b/test/Progress/TARGET.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 substition of the $TARGET string in progress output, including
+overwriting it by setting the overwrite= keyword argument.
+"""
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(universal_newlines=None)
+
+test.write('SConstruct', """\
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress('$TARGET\\r', overwrite=True)
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect = """\
+S1.in\r \rS1.out\rCopy("S1.out", "S1.in")
+ \rS2.in\r \rS2.out\rCopy("S2.out", "S2.in")
+ \rS3.in\r \rS3.out\rCopy("S3.out", "S3.in")
+ \rS4.in\r \rS4.out\rCopy("S4.out", "S4.in")
+ \rSConstruct\r \r.\r"""
+
+if os.linesep != '\n':
+ expect = string.replace(expect, '\n', os.linesep)
+
+test.run(arguments = '-Q .', stdout=expect)
+
+test.pass_test()
diff --git a/test/Progress/dots.py b/test/Progress/dots.py
new file mode 100644
index 0000000..23b3e72
--- /dev/null
+++ b/test/Progress/dots.py
@@ -0,0 +1,60 @@
+#!/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 expected behavior of just telling a Progress() object to print
+a dot for every visited Node.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress('.')
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect = """\
+..Copy("S1.out", "S1.in")
+..Copy("S2.out", "S2.in")
+..Copy("S3.out", "S3.in")
+..Copy("S4.out", "S4.in")
+.."""
+
+test.run(arguments = '-Q .', stdout=expect)
+
+test.pass_test()
diff --git a/test/Progress/file.py b/test/Progress/file.py
new file mode 100644
index 0000000..f0116c0
--- /dev/null
+++ b/test/Progress/file.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 the file= argument to Progress() allows us to redirect the
+progress output.
+"""
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress('stderr: $TARGET\\n', file=open('progress.out', 'w'))
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect = """\
+Copy("S1.out", "S1.in")
+Copy("S2.out", "S2.in")
+Copy("S3.out", "S3.in")
+Copy("S4.out", "S4.in")
+"""
+
+test.run(arguments = '-Q .', stdout=expect)
+
+expect = """\
+stderr: S1.in
+stderr: S1.out
+stderr: S2.in
+stderr: S2.out
+stderr: S3.in
+stderr: S3.out
+stderr: S4.in
+stderr: S4.out
+stderr: SConstruct
+stderr: .
+"""
+
+if os.linesep != '\n':
+ expect = string.replace(expect, '\n', os.linesep)
+
+test.must_match('progress.out', expect)
+
+test.pass_test()
diff --git a/test/Progress/function.py b/test/Progress/function.py
new file mode 100644
index 0000000..2fcb671
--- /dev/null
+++ b/test/Progress/function.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 behavior of passing our own function to Progress().
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import sys
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+def my_progress_function(node, *args, **kw):
+ sys.stderr.write('mpf: %s\\n' % node)
+Progress(my_progress_function)
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect_stdout = """\
+Copy("S1.out", "S1.in")
+Copy("S2.out", "S2.in")
+Copy("S3.out", "S3.in")
+Copy("S4.out", "S4.in")
+"""
+
+expect_stderr = """\
+mpf: S1.in
+mpf: S1.out
+mpf: S2.in
+mpf: S2.out
+mpf: S3.in
+mpf: S3.out
+mpf: S4.in
+mpf: S4.out
+mpf: SConstruct
+mpf: .
+"""
+
+test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr)
+
+test.pass_test()
diff --git a/test/Progress/interval.py b/test/Progress/interval.py
new file mode 100644
index 0000000..767bf20
--- /dev/null
+++ b/test/Progress/interval.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the "interval=" parameter to Progress skips Nodes.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import sys
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress('stderr: $TARGET\\n', file=sys.stderr, interval=2)
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect_stdout = """\
+Copy("S1.out", "S1.in")
+Copy("S2.out", "S2.in")
+Copy("S3.out", "S3.in")
+Copy("S4.out", "S4.in")
+"""
+
+expect_stderr = """\
+stderr: S1.out
+stderr: S2.out
+stderr: S3.out
+stderr: S4.out
+stderr: .
+"""
+
+test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr)
+
+test.pass_test()
diff --git a/test/Progress/object.py b/test/Progress/object.py
new file mode 100644
index 0000000..4dad1a1
--- /dev/null
+++ b/test/Progress/object.py
@@ -0,0 +1,78 @@
+#!/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 passing a callable object to Progress().
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+import sys
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+class my_progress:
+ count = 0
+ def __call__(self, node, *args, **kw):
+ self.count = self.count + 1
+ sys.stderr.write('%s: %s\\n' % (self.count, node))
+Progress(my_progress())
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect_stdout = """\
+Copy("S1.out", "S1.in")
+Copy("S2.out", "S2.in")
+Copy("S3.out", "S3.in")
+Copy("S4.out", "S4.in")
+"""
+
+expect_stderr = """\
+1: S1.in
+2: S1.out
+3: S2.in
+4: S2.out
+5: S3.in
+6: S3.out
+7: S4.in
+8: S4.out
+9: SConstruct
+10: .
+"""
+
+test.run(arguments = '-Q .', stdout=expect_stdout, stderr=expect_stderr)
+
+test.pass_test()
diff --git a/test/Progress/spinner.py b/test/Progress/spinner.py
new file mode 100644
index 0000000..c600b67
--- /dev/null
+++ b/test/Progress/spinner.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 output when a Progress() call is initialized with the list
+that represents a canonical "spinner" on the output.
+"""
+
+import os
+import string
+
+import TestSCons
+
+test = TestSCons.TestSCons(universal_newlines=None)
+
+test.write('SConstruct', r"""
+env = Environment()
+env['BUILDERS']['C'] = Builder(action=Copy('$TARGET', '$SOURCE'))
+Progress(['-\r', '\\\r', '|\r', '/\r'])
+env.C('S1.out', 'S1.in')
+env.C('S2.out', 'S2.in')
+env.C('S3.out', 'S3.in')
+env.C('S4.out', 'S4.in')
+""")
+
+test.write('S1.in', "S1.in\n")
+test.write('S2.in', "S2.in\n")
+test.write('S3.in', "S3.in\n")
+test.write('S4.in', "S4.in\n")
+
+expect = """\
+\\\r|\rCopy("S1.out", "S1.in")
+/\r-\rCopy("S2.out", "S2.in")
+\\\r|\rCopy("S3.out", "S3.in")
+/\r-\rCopy("S4.out", "S4.in")
+\\\r|\r"""
+
+if os.linesep != '\n':
+ expect = string.replace(expect, '\n', os.linesep)
+
+test.run(arguments = '-Q .', stdout=expect)
+
+test.pass_test()
diff --git a/test/QT/installed.py b/test/QT/installed.py
index 8cb9ab1..d746d9e 100644
--- a/test/QT/installed.py
+++ b/test/QT/installed.py
@@ -191,10 +191,11 @@ if test.stdout() != "Hello World\n" or test.stderr() != '' or test.status:
# If so, then print whatever it showed us (which is in and of itself
# an indication that it built correctly) but don't fail the test.
expect = 'cannot connect to X server'
- test.fail_test(test.stdout() != '' or
- string.find(test.stderr(), expect) == -1 or \
- (test.status>>8) != 1)
-
+ test.fail_test(test.stdout())
+ test.fail_test(string.find(test.stderr(), expect) == -1)
+ if test.status != 1 and (test.status>>8) != 1:
+ sys.stdout.write('test_realqt returned status %s\n' % test.status)
+ test.fail_test()
QTDIR = os.environ['QTDIR']
PATH = os.environ['PATH']
diff --git a/test/QT/moc-from-header.py b/test/QT/moc-from-header.py
index 1dbcd0f..2878136 100644
--- a/test/QT/moc-from-header.py
+++ b/test/QT/moc-from-header.py
@@ -92,7 +92,6 @@ test.must_exist(test.workpath('build', moc))
test.run(arguments = "build_dir=1 chdir=1 dup=0 " +
test.workpath('build_dup0', aaa_exe) )
-test.must_exist(['build_dup0', moc],
- ['build_dup0', aaa_exe])
+test.must_exist(['build_dup0', moc])
test.pass_test()
diff --git a/test/SConscript/Return.py b/test/SConscript/Return.py
new file mode 100644
index 0000000..453c0b8
--- /dev/null
+++ b/test/SConscript/Return.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that the Return() function stops processing the SConscript file
+at the point is called, unless the stop= keyword argument is supplied.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+SConscript('SConscript1')
+x = SConscript('SConscript2')
+y, z = SConscript('SConscript3')
+a4, b4 = SConscript('SConscript4')
+print "x =", x
+print "y =", y
+print "z =", z
+print "a4 =", a4
+print "b4 =", b4
+""")
+
+test.write('SConscript1', """\
+print "line 1"
+Return()
+print "line 2"
+""")
+
+test.write('SConscript2', """\
+print "line 3"
+x = 7
+Return('x')
+print "line 4"
+""")
+
+test.write('SConscript3', """\
+print "line 5"
+y = 8
+z = 9
+Return('y z')
+print "line 6"
+""")
+
+test.write('SConscript4', """\
+a4 = 'aaa'
+b4 = 'bbb'
+print "line 7"
+Return('a4', 'b4', stop=False)
+b4 = 'b-after'
+print "line 8"
+""")
+
+expect = """\
+line 1
+line 3
+line 5
+line 7
+line 8
+x = 7
+y = 8
+z = 9
+a4 = aaa
+b4 = bbb
+"""
+
+test.run(arguments = '-q -Q', stdout=expect)
+
+test.pass_test()
diff --git a/test/SWIG/build-dir.py b/test/SWIG/build-dir.py
index 593a26a..58ad0cd 100644
--- a/test/SWIG/build-dir.py
+++ b/test/SWIG/build-dir.py
@@ -37,6 +37,11 @@ import TestSCons
test = TestSCons.TestSCons()
+swig = test.where_is('swig')
+
+if not swig:
+ test.skip_test('Can not find installed "swig", skipping test.\n')
+
# swig-python expects specific filenames.
# the platform specific suffix won't necessarily work.
if sys.platform == 'win32':
@@ -129,9 +134,6 @@ public:
%extend
{
const char* __str__() { return "linalg.Vector()"; }
- int __len__() { return $self->size(); }
- double __getitem__(int key) { return $self->operator[](key); }
- void __setitem__(int key, double value) { $self->operator[](key) = value; }
%pythoncode %{
def __iter__(self):
diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py
index 2dfd322..dd2c938 100644
--- a/test/Scanner/generated.py
+++ b/test/Scanner/generated.py
@@ -411,18 +411,17 @@ int g_3()
test.run(stderr=TestSCons.noisy_ar,
match=TestSCons.match_re_dotall)
-# XXX Note that the generated .h files still get scanned twice,
-# once before they're generated and once after. That's the
-# next thing to fix here.
+# Note that the generated .h files still get scanned twice,
+# but that's really once each as a child of libg_1.o and libg_2.o.
test.must_match("MyCScan.out", """\
libg_1.c: 1
libg_2.c: 1
libg_3.c: 1
-libg_gx.h: 1
+libg_gx.h: 2
libg_gy.h: 1
libg_gz.h: 1
-libg_w.h: 1
+libg_w.h: 2
""")
test.pass_test()
diff --git a/test/Sig.py b/test/Sig.py
new file mode 100644
index 0000000..8565735
--- /dev/null
+++ b/test/Sig.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that we generate the proper warning, but don't die, when someone
+tries to import the SCons.Sig module (which no longer exists) and
+use the things we used to define therein.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+SConstruct = test.workpath('SConstruct')
+
+test.write(SConstruct, """
+import SCons.Sig
+x = SCons.Sig.default_calc
+x = SCons.Sig.default_module
+x = SCons.Sig.MD5.current()
+x = SCons.Sig.MD5.collect()
+x = SCons.Sig.MD5.signature()
+x = SCons.Sig.MD5.to_string()
+x = SCons.Sig.MD5.from_string()
+x = SCons.Sig.TimeStamp.current()
+x = SCons.Sig.TimeStamp.collect()
+x = SCons.Sig.TimeStamp.signature()
+x = SCons.Sig.TimeStamp.to_string()
+x = SCons.Sig.TimeStamp.from_string()
+""")
+
+expect = """
+scons: warning: The SCons.Sig module no longer exists.
+ Remove the following "import SCons.Sig" line to eliminate this warning:
+""" + test.python_file_line(SConstruct, 2)
+
+test.run(arguments = '.', stderr=expect)
+
+test.pass_test()
diff --git a/test/SourceCode.py b/test/SourceCode.py
index 86cc2a6..b74f8b1 100644
--- a/test/SourceCode.py
+++ b/test/SourceCode.py
@@ -59,7 +59,7 @@ env = Environment(BUILDERS={'Cat':Builder(action=cat)}, SUBDIR='sub')
env.SourceCode('$SUBDIR', Builder(action=sc_cat, env=env))
env.Cat('aaa.out', 'sub/aaa.in')
bbb_in = File('sub/bbb.in')
-bbb_in.is_pseudo_derived()
+bbb_in.is_derived()
env.Cat('bbb.out', bbb_in)
env.Cat('ccc.out', 'sub/ccc.in')
env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out'])
diff --git a/test/SourceSignatures.py b/test/SourceSignatures.py
deleted file mode 100644
index b85f8ec..0000000
--- a/test/SourceSignatures.py
+++ /dev/null
@@ -1,268 +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 imp
-import os
-import os.path
-import time
-
-import TestSCons
-
-test = TestSCons.TestSCons()
-
-test.write('SConstruct', """
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'f3.out', source = 'f3.in')
-env.B(target = 'f4.out', source = 'f4.in')
-
-SourceSignatures('timestamp')
-""")
-
-test.write('f1.in', "f1.in\n")
-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 f2.out f3.out f4.out',
- stdout = test.wrap_stdout("""\
-scons: `f1.out' is up to date.
-build(["f2.out"], ["f2.in"])
-scons: `f3.out' is up to date.
-build(["f4.out"], ["f4.in"])
-"""))
-
-os.utime(test.workpath('f1.in'),
- (os.path.getatime(test.workpath('f1.in')),
- os.path.getmtime(test.workpath('f1.in'))+10))
-os.utime(test.workpath('f3.in'),
- (os.path.getatime(test.workpath('f3.in')),
- os.path.getmtime(test.workpath('f3.in'))+10))
-
-test.run(arguments = 'f1.out f2.out f3.out f4.out',
- stdout = test.wrap_stdout("""\
-build(["f1.out"], ["f1.in"])
-scons: `f2.out' is up to date.
-build(["f3.out"], ["f3.in"])
-scons: `f4.out' is up to date.
-"""))
-
-test.write('SConstruct', """
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'f3.out', source = 'f3.in')
-env.B(target = 'f4.out', source = 'f4.in')
-
-SourceSignatures('MD5')
-""")
-
-test.write('f1.in', "f1.in\n")
-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 f2.out f3.out f4.out',
- stdout = test.wrap_stdout("""\
-scons: `f1.out' is up to date.
-build(["f2.out"], ["f2.in"])
-scons: `f3.out' is up to date.
-build(["f4.out"], ["f4.in"])
-"""))
-
-os.utime(test.workpath('f1.in'),
- (os.path.getatime(test.workpath('f1.in')),
- os.path.getmtime(test.workpath('f1.in'))+10))
-os.utime(test.workpath('f3.in'),
- (os.path.getatime(test.workpath('f3.in')),
- os.path.getmtime(test.workpath('f3.in'))+10))
-
-test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
-
-test.write('SConstruct', """
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'f3.out', source = 'f3.in')
-env.B(target = 'f4.out', source = 'f4.in')
-""")
-
-test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
-
-test.write('SConstruct', """
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env2 = env.Clone()
-env2.SourceSignatures('MD5')
-env.B(target = 'f5.out', source = 'f5.in')
-env.B(target = 'f6.out', source = 'f6.in')
-env2.B(target = 'f7.out', source = 'f7.in')
-env2.B(target = 'f8.out', source = 'f8.in')
-
-SourceSignatures('timestamp')
-""")
-
-test.write('f5.in', "f5.in\n")
-test.write('f6.in', "f6.in\n")
-test.write('f7.in', "f7.in\n")
-test.write('f8.in', "f8.in\n")
-
-test.run(arguments = 'f5.out f7.out')
-
-test.run(arguments = 'f5.out f6.out f7.out f8.out',
- stdout = test.wrap_stdout("""\
-scons: `f5.out' is up to date.
-build(["f6.out"], ["f6.in"])
-scons: `f7.out' is up to date.
-build(["f8.out"], ["f8.in"])
-"""))
-
-os.utime(test.workpath('f5.in'),
- (os.path.getatime(test.workpath('f5.in')),
- os.path.getmtime(test.workpath('f5.in'))+10))
-os.utime(test.workpath('f7.in'),
- (os.path.getatime(test.workpath('f7.in')),
- os.path.getmtime(test.workpath('f7.in'))+10))
-
-test.run(arguments = 'f5.out f6.out f7.out f8.out',
- stdout = test.wrap_stdout("""\
-build(["f5.out"], ["f5.in"])
-scons: `f6.out' is up to date.
-scons: `f7.out' is up to date.
-scons: `f8.out' is up to date.
-"""))
-
-test.up_to_date(arguments = 'f5.out f6.out f7.out f8.out')
-
-# Ensure that switching signature types causes a rebuild:
-test.write('SConstruct', """
-SourceSignatures('MD5')
-
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'switch.out', source = 'switch.in')
-""")
-
-test.write('switch.in', "switch.in\n")
-
-switch_out_switch_in = test.wrap_stdout('build(["switch.out"], ["switch.in"])\n')
-
-test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
-
-test.up_to_date(arguments = 'switch.out')
-
-test.write('SConstruct', """
-SourceSignatures('timestamp')
-
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'switch.out', source = 'switch.in')
-""")
-
-test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
-
-test.up_to_date(arguments = 'switch.out')
-
-test.write('SConstruct', """
-SourceSignatures('MD5')
-
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'switch.out', source = 'switch.in')
-""")
-
-test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
-
-test.up_to_date(arguments = 'switch.out')
-
-test.write('switch.in', "switch.in 2\n")
-
-test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
-
-
-# Test both implicit_cache and timestamp signatures at the same time:
-test.write('SConstruct', """
-SetOption('implicit_cache', 1)
-SourceSignatures('timestamp')
-
-def build(env, target, source):
- open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
-B = Builder(action = build)
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'both.out', source = 'both.in')
-""")
-
-test.write('both.in', "both.in 1\n")
-
-both_out_both_in = test.wrap_stdout('build(["both.out"], ["both.in"])\n')
-
-test.run(arguments = 'both.out', stdout = both_out_both_in)
-
-time.sleep(2)
-
-test.write('both.in', "both.in 2\n")
-
-test.run(arguments = 'both.out', stdout = both_out_both_in)
-
-time.sleep(2)
-
-test.write('both.in', "both.in 3\n")
-
-test.run(arguments = 'both.out', stdout = both_out_both_in)
-
-time.sleep(2)
-
-test.write('both.in', "both.in 4\n")
-
-test.run(arguments = 'both.out', stdout = both_out_both_in)
-
-time.sleep(2)
-
-test.up_to_date(arguments = 'both.out')
-
-test.pass_test()
diff --git a/test/SourceSignatures/basic.py b/test/SourceSignatures/basic.py
new file mode 100644
index 0000000..7042fac
--- /dev/null
+++ b/test/SourceSignatures/basic.py
@@ -0,0 +1,124 @@
+#!/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 os.path
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+
+
+base_sconstruct_contents = """\
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+env.B(target = 'f3.out', source = 'f3.in')
+env.B(target = 'f4.out', source = 'f4.in')
+"""
+
+def write_SConstruct(test, sigtype):
+ contents = base_sconstruct_contents
+ if sigtype:
+ contents = contents + ("\nSourceSignatures('%s')\n" % sigtype)
+ test.write('SConstruct', contents)
+
+
+
+write_SConstruct(test, 'timestamp')
+
+test.write('f1.in', "f1.in\n")
+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 f2.out f3.out f4.out',
+ stdout = test.wrap_stdout("""\
+scons: `f1.out' is up to date.
+build(["f2.out"], ["f2.in"])
+scons: `f3.out' is up to date.
+build(["f4.out"], ["f4.in"])
+"""))
+
+
+
+os.utime(test.workpath('f1.in'),
+ (os.path.getatime(test.workpath('f1.in')),
+ os.path.getmtime(test.workpath('f1.in'))+10))
+os.utime(test.workpath('f3.in'),
+ (os.path.getatime(test.workpath('f3.in')),
+ os.path.getmtime(test.workpath('f3.in'))+10))
+
+test.run(arguments = 'f1.out f2.out f3.out f4.out',
+ stdout = test.wrap_stdout("""\
+build(["f1.out"], ["f1.in"])
+scons: `f2.out' is up to date.
+build(["f3.out"], ["f3.in"])
+scons: `f4.out' is up to date.
+"""))
+
+
+
+# Switching to content signatures from timestamps should rebuild,
+# because we didn't record the content signatures last time.
+
+write_SConstruct(test, 'MD5')
+
+test.not_up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+test.sleep()
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+test.write('f3.in', "f3.in\n")
+test.write('f4.in', "f4.in\n")
+
+test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+test.touch('f1.in', os.path.getmtime(test.workpath('f1.in'))+10)
+test.touch('f3.in', os.path.getmtime(test.workpath('f3.in'))+10)
+
+test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+write_SConstruct(test, None)
+
+test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+test.pass_test()
diff --git a/test/SourceSignatures/env.py b/test/SourceSignatures/env.py
new file mode 100644
index 0000000..3bef2a6
--- /dev/null
+++ b/test/SourceSignatures/env.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__"
+
+"""
+Test that use of env.SourceSignatures() correctly overrides the
+default behavior.
+"""
+
+import os
+import os.path
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+base_sconstruct_contents = """\
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env2 = env.Copy()
+env2.SourceSignatures('%s')
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+env2.B(target = 'f3.out', source = 'f3.in')
+env2.B(target = 'f4.out', source = 'f4.in')
+
+SourceSignatures('%s')
+"""
+
+def write_SConstruct(test, env_sigtype, default_sigtype):
+ contents = base_sconstruct_contents % (env_sigtype, default_sigtype)
+ test.write('SConstruct', contents)
+
+
+
+write_SConstruct(test, 'MD5', 'timestamp')
+
+test.write('f1.in', "f1.in\n")
+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 f2.out f3.out f4.out',
+ stdout = test.wrap_stdout("""\
+scons: `f1.out' is up to date.
+build(["f2.out"], ["f2.in"])
+scons: `f3.out' is up to date.
+build(["f4.out"], ["f4.in"])
+"""))
+
+
+
+test.sleep()
+
+test.touch('f1.in')
+test.touch('f3.in')
+
+test.run(arguments = 'f1.out f2.out f3.out f4.out',
+ stdout = test.wrap_stdout("""\
+build(["f1.out"], ["f1.in"])
+scons: `f2.out' is up to date.
+scons: `f3.out' is up to date.
+scons: `f4.out' is up to date.
+"""))
+
+test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out')
+
+
+
+test.pass_test()
diff --git a/test/SourceSignatures/implicit-cache.py b/test/SourceSignatures/implicit-cache.py
new file mode 100644
index 0000000..de66b72
--- /dev/null
+++ b/test/SourceSignatures/implicit-cache.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__"
+
+"""
+Test the simultaneous use of implicit_cache and
+SourceSignatures('timestamp')
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+SetOption('implicit_cache', 1)
+SourceSignatures('timestamp')
+
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'both.out', source = 'both.in')
+""")
+
+both_out_both_in = test.wrap_stdout('build(["both.out"], ["both.in"])\n')
+
+
+
+test.write('both.in', "both.in 1\n")
+
+test.run(arguments = 'both.out', stdout = both_out_both_in)
+
+
+
+test.sleep(2)
+
+test.write('both.in', "both.in 2\n")
+
+test.run(arguments = 'both.out', stdout = both_out_both_in)
+
+
+
+test.sleep(2)
+
+test.write('both.in', "both.in 3\n")
+
+test.run(arguments = 'both.out', stdout = both_out_both_in)
+
+
+
+test.sleep(2)
+
+test.write('both.in', "both.in 4\n")
+
+test.run(arguments = 'both.out', stdout = both_out_both_in)
+
+
+
+test.sleep(2)
+
+test.up_to_date(arguments = 'both.out')
+
+
+
+test.pass_test()
diff --git a/test/SourceSignatures/no-csigs.py b/test/SourceSignatures/no-csigs.py
new file mode 100644
index 0000000..3702901
--- /dev/null
+++ b/test/SourceSignatures/no-csigs.py
@@ -0,0 +1,70 @@
+
+#!/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 os.path
+
+import TestSConsign
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+
+test.write('SConstruct', """\
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'f1.out', source = 'f1.in')
+env.B(target = 'f2.out', source = 'f2.in')
+SourceSignatures('timestamp')
+""")
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+
+test.run(arguments = '.')
+
+
+
+expect = r"""=== .:
+SConstruct: None \d+ \d+
+f1.in: None \d+ \d+
+f1.out: \S+ \d+ \d+
+ f1.in: None \d+ \d+
+ \S+ \[build\(target, source, env\)\]
+f2.in: None \d+ \d+
+f2.out: \S+ \d+ \d+
+ f2.in: None \d+ \d+
+ \S+ \[build\(target, source, env\)\]
+"""
+
+test.run_sconsign(arguments = test.workpath('.sconsign'),
+ stdout = expect)
+
+
+
+test.pass_test()
diff --git a/test/SourceSignatures/overrides.py b/test/SourceSignatures/overrides.py
new file mode 100644
index 0000000..cf83488
--- /dev/null
+++ b/test/SourceSignatures/overrides.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Make sure that SourceSignatures() works when overrides are used on a
+Builder call. (Previous implementations used methods that would stay
+bound to the underlying construction environment, which in this case
+meant ignoring the 'timestamp' setting and still using the underlying
+content signature.)
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+DefaultEnvironment().SourceSignatures('MD5')
+env = Environment()
+env.SourceSignatures('timestamp')
+env.Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=1)
+""")
+
+test.write('foo.in', "foo.in 1\n")
+
+test.run(arguments = 'foo.out')
+
+test.sleep()
+
+test.write('foo.in', "foo.in 1\n")
+
+test.not_up_to_date(arguments = 'foo.out')
+
+test.pass_test()
diff --git a/test/SourceSignatures/switch-rebuild.py b/test/SourceSignatures/switch-rebuild.py
new file mode 100644
index 0000000..85c2b22
--- /dev/null
+++ b/test/SourceSignatures/switch-rebuild.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__"
+
+"""
+Test that switching SourceSignature() types no longer causes rebuilds.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+
+base_sconstruct_contents = """\
+SourceSignatures('%s')
+
+def build(env, target, source):
+ open(str(target[0]), 'wt').write(open(str(source[0]), 'rt').read())
+B = Builder(action = build)
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'switch.out', source = 'switch.in')
+"""
+
+def write_SConstruct(test, sig_type):
+ contents = base_sconstruct_contents % sig_type
+ test.write('SConstruct', contents)
+
+
+write_SConstruct(test, 'MD5')
+
+test.write('switch.in', "switch.in\n")
+
+switch_out_switch_in = test.wrap_stdout('build(["switch.out"], ["switch.in"])\n')
+
+test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
+
+test.up_to_date(arguments = 'switch.out')
+
+
+
+write_SConstruct(test, 'timestamp')
+
+test.up_to_date(arguments = 'switch.out')
+
+
+
+write_SConstruct(test, 'MD5')
+
+test.not_up_to_date(arguments = 'switch.out')
+
+
+
+test.write('switch.in', "switch.in 2\n")
+
+test.run(arguments = 'switch.out', stdout = switch_out_switch_in)
+
+
+
+test.pass_test()
diff --git a/test/TEX/auxiliaries.py b/test/TEX/auxiliaries.py
index e189d57..8df2e79 100644
--- a/test/TEX/auxiliaries.py
+++ b/test/TEX/auxiliaries.py
@@ -141,7 +141,7 @@ if pdf_output_1 != pdf_output_2:
import sys
test.write(['build', 'docs', 'test.normalized.1.pdf'], pdf_output_1)
test.write(['build', 'docs', 'test.normalized.2.pdf'], pdf_output_2)
- sys.stdout.write("***** 1 and 2 are different!\n")
+ sys.stdout.write("***** 1.pdf and 2.pdf are different!\n")
sys.stdout.write(test.diff_substr(pdf_output_1, pdf_output_2, 80, 80) + '\n')
sys.stdout.write("Output from run 1:\n")
sys.stdout.write(test.stdout(-1) + '\n')
@@ -150,7 +150,16 @@ if pdf_output_1 != pdf_output_2:
sys.stdout.flush()
test.fail_test()
-assert ps_output_1 == ps_output_2, test.diff_substr(ps_output_1, ps_output_2, 80, 80)
+if ps_output_1 != ps_output_2:
+ import sys
+ sys.stdout.write("***** 1.ps and 2.ps are different!\n")
+ sys.stdout.write(test.diff_substr(ps_output_1, ps_output_2, 80, 80) + '\n')
+ sys.stdout.write("Output from run 1:\n")
+ sys.stdout.write(test.stdout(-1) + '\n')
+ sys.stdout.write("Output from run 2:\n")
+ sys.stdout.write(test.stdout() + '\n')
+ sys.stdout.flush()
+ test.fail_test()
diff --git a/test/TEX/clean.py b/test/TEX/clean.py
new file mode 100644
index 0000000..6615fc9
--- /dev/null
+++ b/test/TEX/clean.py
@@ -0,0 +1,94 @@
+#!/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__"
+
+"""
+Check that all auxilary files created by LaTeX are properly cleaned by scons -c.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+latex = test.where_is('latex')
+
+if not latex:
+ test.skip_test("Could not find tex or latex; skipping test(s).\n")
+
+# package hyperref generates foo.out
+# package comment generates comment.cut
+# todo: add makeindex etc.
+input_file = r"""
+\documentclass{article}
+\usepackage{hyperref}
+\usepackage{comment}
+\specialcomment{foocom}{}{}
+\begin{document}
+\begin{foocom}
+Hi
+\end{foocom}
+As stated in \cite{X}, this is a bug-a-boo.
+\bibliography{fooref}
+\bibliographystyle{plain}
+\end{document}
+"""
+
+bibfile = r"""
+@Article{X,
+ author = "Mr. X",
+ title = "A determination of bug-a-boo-ness",
+ journal = "Journal of B.a.B.",
+ year = 1920,
+ volume = 62,
+ pages = 291
+}
+"""
+
+test.write('SConstruct', """\
+DVI( "foo.ltx" )
+""")
+
+test.write('foo.ltx', input_file)
+test.write('fooref.bib', bibfile)
+
+test.run()
+
+test.must_exist('foo.log')
+test.must_exist('foo.aux')
+test.must_exist('foo.bbl')
+test.must_exist('foo.blg')
+test.must_exist('comment.cut')
+test.must_exist('foo.out')
+
+test.run(arguments = '-c')
+
+test.must_not_exist('foo.log')
+test.must_not_exist('foo.aux')
+test.must_not_exist('foo.bbl')
+test.must_not_exist('foo.blg')
+test.must_not_exist('comment.cut')
+test.must_not_exist('foo.out')
+
+test.pass_test()
diff --git a/test/TargetSignatures.py b/test/TargetSignatures/build-content.py
index c3b506b..2cd7a89 100644
--- a/test/TargetSignatures.py
+++ b/test/TargetSignatures/build-content.py
@@ -24,17 +24,26 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""
+Verify basic interaction of the historic TargetSignatures('build')
+and TargetSignatures('content') settings, overriding one with
+the other in specific construction environments.
+"""
+
import TestSCons
test = TestSCons.TestSCons()
-test.write('SConstruct', """
+
+
+sconstruct_contents = """\
env = Environment()
def copy1(env, source, target):
open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
def copy2(env, source, target):
+ %s
return copy1(env, source, target)
env['BUILDERS']['Copy1'] = Builder(action=copy1)
@@ -44,12 +53,20 @@ env.Copy2('foo.mid', 'foo.in')
env.Copy1('foo.out', 'foo.mid')
env2 = env.Clone()
-env2.TargetSignatures('build')
+env2.TargetSignatures('%s')
env2.Copy2('bar.mid', 'bar.in')
env2.Copy1('bar.out', 'bar.mid')
-TargetSignatures('content')
-""")
+TargetSignatures('%s')
+"""
+
+def write_SConstruct(test, *args):
+ contents = sconstruct_contents % args
+ test.write('SConstruct', contents)
+
+
+
+write_SConstruct(test, '', 'build', 'content')
test.write('foo.in', 'foo.in')
test.write('bar.in', 'bar.in')
@@ -64,29 +81,12 @@ copy1(["foo.out"], ["foo.mid"])
test.up_to_date(arguments='bar.out foo.out')
-test.write('SConstruct', """
-env = Environment()
-
-def copy1(env, source, target):
- open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
-
-def copy2(env, source, target):
- x = 2 # added this line
- return copy1(env, source, target)
-
-env['BUILDERS']['Copy1'] = Builder(action=copy1)
-env['BUILDERS']['Copy2'] = Builder(action=copy2)
-env.Copy2('foo.mid', 'foo.in')
-env.Copy1('foo.out', 'foo.mid')
-env2 = env.Clone()
-env2.TargetSignatures('build')
-env2.Copy2('bar.mid', 'bar.in')
-env2.Copy1('bar.out', 'bar.mid')
+# Change the code in the the copy2() function, which should change
+# its content and trigger a rebuild of the targets built with it.
-TargetSignatures('content')
-""")
+write_SConstruct(test, 'x = 2 # added this line', 'build', 'content')
test.run(arguments="bar.out foo.out",
stdout=test.wrap_stdout("""\
@@ -96,58 +96,21 @@ copy2(["foo.mid"], ["foo.in"])
scons: `foo.out' is up to date.
"""))
-test.write('SConstruct', """
-env = Environment()
-
-def copy1(env, source, target):
- open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
-
-def copy2(env, source, target):
- x = 2 # added this line
- return copy1(env, source, target)
-
-env['BUILDERS']['Copy1'] = Builder(action=copy1)
-env['BUILDERS']['Copy2'] = Builder(action=copy2)
-
-env.Copy2('foo.mid', 'foo.in')
-env.Copy1('foo.out', 'foo.mid')
-
-env2 = env.Copy()
-env2.TargetSignatures('content')
-env2.Copy2('bar.mid', 'bar.in')
-env2.Copy1('bar.out', 'bar.mid')
-
-TargetSignatures('build')
-""")
-test.run(arguments="bar.out foo.out",
- stdout=test.wrap_stdout("""\
-copy1(["bar.out"], ["bar.mid"])
-copy1(["foo.out"], ["foo.mid"])
-"""))
-test.write('SConstruct', """
-env = Environment()
+# Swapping content and build signatures no longer causes a rebuild
+# because we record the right underlying information regardless.
-def copy1(env, source, target):
- open(str(target[0]), 'wb').write(open(str(source[0]), 'rb').read())
+write_SConstruct(test, 'x = 2 # added this line', 'content', 'build')
-def copy2(env, source, target):
- return copy1(env, source, target)
+test.up_to_date(arguments="bar.out foo.out")
-env['BUILDERS']['Copy1'] = Builder(action=copy1)
-env['BUILDERS']['Copy2'] = Builder(action=copy2)
-env.Copy2('foo.mid', 'foo.in')
-env.Copy1('foo.out', 'foo.mid')
-env2 = env.Copy()
-env2.TargetSignatures('content')
-env2.Copy2('bar.mid', 'bar.in')
-env2.Copy1('bar.out', 'bar.mid')
+# Change the code in the the copy2() function back again, which should
+# trigger another rebuild of the targets built with it.
-TargetSignatures('build')
-""")
+write_SConstruct(test, '', 'content', 'build')
test.run(arguments='bar.out foo.out',
stdout=test.wrap_stdout("""\
@@ -158,4 +121,5 @@ copy1(["foo.out"], ["foo.mid"])
"""))
+
test.pass_test()
diff --git a/test/TargetSignatures/content.py b/test/TargetSignatures/content.py
new file mode 100644
index 0000000..8d9f213
--- /dev/null
+++ b/test/TargetSignatures/content.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 use of the TargetSignatures('content') setting to override
+SourceSignatures('timestamp') settings.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+
+
+test.write('SConstruct', """\
+env = Environment()
+
+def copy(env, source, target):
+ fp = open(str(target[0]), 'wb')
+ for s in source:
+ fp.write(open(str(s), 'rb').read())
+ fp.close()
+
+copyAction = Action(copy, "Copying $TARGET")
+
+SourceSignatures('timestamp')
+
+env['BUILDERS']['Copy'] = Builder(action=copyAction)
+
+env.Copy('foo.out', 'foo.in')
+
+env2 = env.Clone()
+env2.TargetSignatures('content')
+env2.Copy('bar.out', 'bar.in')
+AlwaysBuild('bar.out')
+
+env.Copy('final', ['foo.out', 'bar.out', 'extra.in'])
+env.Ignore('final', 'extra.in')
+""")
+
+test.write('foo.in', "foo.in\n")
+test.write('bar.in', "bar.in\n")
+test.write('extra.in', "extra.in 1\n")
+
+test.run()
+
+test.must_match('final', "foo.in\nbar.in\nextra.in 1\n")
+
+test.sleep()
+test.write('extra.in', "extra.in 2\n")
+
+test.run()
+
+test.must_match('final', "foo.in\nbar.in\nextra.in 1\n")
+
+
+
+test.pass_test()
diff --git a/test/TargetSignatures/overrides.py b/test/TargetSignatures/overrides.py
new file mode 100644
index 0000000..5d9dd99
--- /dev/null
+++ b/test/TargetSignatures/overrides.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Make sure that TargetSignatures() works when overrides are used on a
+Builder call. Previous implementations used methods that would stay
+bound to the underlying construction environment and cause weird
+behavior like infinite recursion.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """\
+env = Environment()
+env.TargetSignatures('content')
+env.Command('foo.out', 'foo.mid', Copy('$TARGET', '$SOURCE'), FOO=1)
+env.Command('foo.mid', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=2)
+""")
+
+test.write('foo.in', "foo.in\n")
+
+test.run(arguments = '.')
+
+test.must_match('foo.mid', "foo.in\n")
+test.must_match('foo.out', "foo.in\n")
+
+test.pass_test()
diff --git a/test/Value.py b/test/Value.py
index 85fcbd1..fd7afb7 100644
--- a/test/Value.py
+++ b/test/Value.py
@@ -35,13 +35,9 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons(match=TestCmd.match_re)
-# Run all of the tests with both types of source signature
-# to make sure there's no difference in behavior.
-for source_signature in ['MD5', 'timestamp']:
+python = TestSCons.python
- print "Testing Value node with source signatures:", source_signature
-
- test.write('SConstruct', """
+SConstruct_content = """
SourceSignatures(r'%(source_signature)s')
class Custom:
@@ -57,7 +53,7 @@ def create(target, source, env):
env = Environment()
env['BUILDERS']['B'] = Builder(action = create)
-env['BUILDERS']['S'] = Builder(action = '%(_python_)s put $SOURCES into $TARGET')
+env['BUILDERS']['S'] = Builder(action = r'%(_python_)s put.py $SOURCES into $TARGET')
env.B('f1.out', Value(P))
env.B('f2.out', env.Value(L))
env.B('f3.out', Value(C))
@@ -75,15 +71,23 @@ env['BUILDERS']['B3'] = Builder(action = create_value_file)
V = Value('my value')
env.B2(V, 'f3.out')
env.B3('f5.out', V)
-""" % locals())
+"""
- test.write('put', """
+test.write('put.py', """\
import os
import string
import sys
open(sys.argv[-1],'wb').write(string.join(sys.argv[1:-2]))
""")
+# Run all of the tests with both types of source signature
+# to make sure there's no difference in behavior.
+for source_signature in ['MD5', 'timestamp']:
+
+ print "Testing Value node with source signatures:", source_signature
+
+ test.write('SConstruct', SConstruct_content % locals())
+
test.run(arguments='-c')
test.run()
diff --git a/test/bad-drive.py b/test/bad-drive.py
index a642a7c..f07da2b 100644
--- a/test/bad-drive.py
+++ b/test/bad-drive.py
@@ -93,7 +93,7 @@ test.fail_test(test.read('aaa.out') != "aaa.in\n")
# becomes an issue or some refactoring restores the old behavior.
test.run(arguments = bad_drive + 'not_mentioned',
- stderr = "scons: *** No drive `%s' for target `%snot_mentioned'. Stop.\n" % (bad_drive, bad_drive),
+ stderr = "scons: *** Do not know how to make target `%snot_mentioned'. Stop.\n" % (bad_drive),
status = 2)
test.run(arguments = bad_drive + 'no_target_1',
diff --git a/test/chained-build.py b/test/chained-build.py
index 9d87347..6ec9d1c 100644
--- a/test/chained-build.py
+++ b/test/chained-build.py
@@ -59,6 +59,7 @@ test.write(['w1', 'foo.in'], "foo.in 1")
test.run(chdir='w1',
arguments="--max-drift=0 -f SConstruct1 foo.mid",
stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n'))
+
test.run(chdir='w1',
arguments="--max-drift=0 -f SConstruct2 foo.out",
stdout = test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n'))
@@ -66,6 +67,7 @@ test.run(chdir='w1',
test.up_to_date(chdir='w1',
options="--max-drift=0 -f SConstruct1",
arguments="foo.mid")
+
test.up_to_date(chdir='w1',
options="--max-drift=0 -f SConstruct2",
arguments="foo.out")
@@ -73,28 +75,23 @@ test.up_to_date(chdir='w1',
test.sleep() # make sure foo.in rewrite has new mod-time
test.write(['w1', 'foo.in'], "foo.in 2")
-test.run(chdir='w1',
- arguments="--max-drift=0 -f SConstruct1 foo.mid",
- stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n'))
# Because we're using --max-drift=0, we use the cached csig value
-# and think that foo.mid hasn't changed even though it has on disk.
+# and think that foo.in hasn't changed even though it has on disk.
test.up_to_date(chdir='w1',
- options="--max-drift=0 -f SConstruct2",
- arguments="foo.out")
+ options="--max-drift=0 -f SConstruct1",
+ arguments="foo.mid")
+# Now try with --max-drift disabled. The build of foo.out should still
+# be considered up-to-date, but the build of foo.mid now detects the
+# change and rebuilds, too, which then causes a rebuild of foo.out.
test.up_to_date(chdir='w1',
- options="--max-drift=0 -f SConstruct1",
- arguments="foo.mid")
-test.up_to_date(chdir='w1',
- options="--max-drift=0 -f SConstruct2",
+ options="--max-drift=-1 -f SConstruct2",
arguments="foo.out")
-# Now try with --max-drift disabled. The build of foo.mid should still
-# be considered up-to-date, but the build of foo.out now detects the
-# change and rebuilds, too.
-test.up_to_date(chdir='w1',
- options="--max-drift=-1 -f SConstruct1",
- arguments="foo.mid")
+test.run(chdir='w1',
+ arguments="--max-drift=-1 -f SConstruct1 foo.mid",
+ stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n'))
+
test.run(chdir='w1',
arguments="--max-drift=-1 -f SConstruct2 foo.out",
stdout = test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n'))
diff --git a/test/exceptions.py b/test/exceptions.py
index 34c24f4..c4bfb37 100644
--- a/test/exceptions.py
+++ b/test/exceptions.py
@@ -65,7 +65,7 @@ test.run(arguments = "-j2 foo.out", stderr = expected_stderr, status = 2)
# Verify that exceptions caused by exit values of builder actions are
-# correectly signalled, for both Serial and Parallel jobs.
+# correctly signalled, for both Serial and Parallel jobs.
test.write('myfail.py', r"""\
import sys
@@ -75,12 +75,12 @@ sys.exit(1)
test.write(SConstruct_path, """
Fail = Builder(action = r'%(_python_)s myfail.py $TARGETS $SOURCE')
env = Environment(BUILDERS = { 'Fail' : Fail })
-env.Fail(target = 'f1', source = 'f1.in')
+env.Fail(target = 'out.f1', source = 'in.f1')
""" % locals())
-test.write('f1.in', "f1.in\n")
+test.write('in.f1', "in.f1\n")
-expected_stderr = "scons: \*\*\* \[f1\] Error 1\n"
+expected_stderr = "scons: \\*\\*\\* \\[out.f1\\] Error 1\n"
test.run(arguments = '.', status = 2, stderr = expected_stderr)
test.run(arguments = '-j2 .', status = 2, stderr = expected_stderr)
@@ -93,13 +93,14 @@ test.run(arguments = '-j2 .', status = 2, stderr = expected_stderr)
test.write(SConstruct_path, """
Fail = Builder(action = r'%(_python_)s myfail.py $TARGETS $SOURCE')
env = Environment(BUILDERS = { 'Fail' : Fail })
-env.Fail(target = 'f1', source = 'f1.in')
-env.Fail(target = 'f2', source = 'f2.in')
-env.Fail(target = 'f3', source = 'f3.in')
+env.Fail(target = 'out.f1', source = 'in.f1')
+env.Fail(target = 'out.f2', source = 'in.f2')
+env.Fail(target = 'out.f3', source = 'in.f3')
""" % locals())
-# f2.in is not created to cause a Task.prepare exception
-test.write('f3.in', 'f3.in\n')
+# in.f2 is not created to cause a Task.prepare exception
+test.write('in.f1', 'in.f1\n')
+test.write('in.f3', 'in.f3\n')
# In Serial task mode, get the first exception and stop
test.run(arguments = '.', status = 2, stderr = expected_stderr)
@@ -107,24 +108,32 @@ test.run(arguments = '.', status = 2, stderr = expected_stderr)
# In Parallel task mode, we will get all three exceptions.
expected_stderr_list = [
- expected_stderr,
- "scons: \*\*\* Source `f2\.in' not found, needed by target `f2'\. Stop\.\n",
- string.replace(expected_stderr, 'f1', 'f3')
- ]
-
-# Unfortunately, we aren't guaranteed what order we will get the
-# exceptions in...
-orders = [ (1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1) ]
-otexts = []
-for A,B,C in orders:
- otexts.append("%s%s%s"%(expected_stderr_list[A-1],
- expected_stderr_list[B-1],
- expected_stderr_list[C-1]))
-
-
-expected_stderrs = "(" + string.join(otexts, "|") + ")"
-
-test.run(arguments = '-j3 .', status = 2, stderr = expected_stderrs)
+ "scons: *** [out.f1] Error 1\n",
+ "scons: *** Source `in.f2' not found, needed by target `out.f2'. Stop.\n",
+ "scons: *** [out.f3] Error 1\n",
+]
+
+# To get all three exceptions simultaneously, we execute -j7 to create
+# one thread each for the SConstruct file and {in,out}.f[123]. Note that
+# it's important that the input (source) files sort earlier alphabetically
+# than the output files, so they're visited first in the dependency graph
+# walk of '.' and are already considered up-to-date when we kick off the
+# "simultaneous" builds of the output (target) files.
+
+test.run(arguments = '-j7 .', status = 2, stderr = None)
+
+missing = []
+for es in expected_stderr_list:
+ if string.find(test.stderr(), es) == -1:
+ missing.append(es)
+
+if missing:
+ sys.stderr.write("Missing the following lines from stderr:\n")
+ for m in missing:
+ sys.stderr.write(m)
+ sys.stderr.write('STDERR ===============================================\n')
+ sys.stderr.write(test.stderr())
+ test.fail_test(1)
test.pass_test()
diff --git a/test/explain/get_csig.py b/test/explain/get_csig.py
new file mode 100644
index 0000000..4bf4981
--- /dev/null
+++ b/test/explain/get_csig.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 we can call get_csig() from a function action without
+causing problems. (This messed up a lot of internal state before
+the Big Signature Refactoring.)
+
+Test case courtesy of Damyan Pepper.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+args = "--debug=explain"
+
+test.write('SConstruct', """\
+env = Environment()
+
+def action( source, target, env ):
+ target[0].get_csig()
+ f = open( str(target[0]), 'w' )
+ for s in source:
+ f.write( s.get_contents() )
+ f.close()
+
+builder = env.Builder( action=action )
+
+builder( env, target = "target.txt", source = "source.txt" )
+""")
+
+test.write("source.txt", "source.txt 1\n")
+
+test.run(arguments=args)
+
+
+
+test.write("source.txt", "source.txt 2")
+
+
+
+expect_rebuild = test.wrap_stdout("""\
+scons: rebuilding `target.txt' because `source.txt' changed
+action(["target.txt"], ["source.txt"])
+""")
+
+test.not_up_to_date(arguments=args)
+
+
+
+test.pass_test()
diff --git a/test/implicit-cache/basic.py b/test/implicit-cache/basic.py
index 0c9196c..265f589 100644
--- a/test/implicit-cache/basic.py
+++ b/test/implicit-cache/basic.py
@@ -41,7 +41,13 @@ test = TestSCons.TestSCons()
test.subdir('include', 'subdir', ['subdir', 'include'], 'inc2')
+# Set TargetSignatures('build') because a lot of the test below expect
+# the old behavior of non-essential changes in .h files will propagate
+# and cause the executable file to be re-linked as well (even if the
+# object file was rebuilt to the exact same contents as last time).
+
test.write('SConstruct', """
+TargetSignatures('build')
env = Environment(CPPPATH = Split('inc2 include'))
obj = env.Object(target='prog', source='subdir/prog.c')
env.Program(target='prog', source=obj)
diff --git a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py
new file mode 100644
index 0000000..47acc2f
--- /dev/null
+++ b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py
@@ -0,0 +1,125 @@
+#!/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 $IMPLICIT_COMMAND_DEPENDENCIES variable controls
+whether or not the implicit dependency on executed commands
+is added to targets.
+"""
+
+import TestSCons
+
+python = TestSCons.python
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+generate_build_py_py_contents = """\
+#!%(python)s
+import os
+import sys
+
+open(sys.argv[1], 'w').write('''\
+#!/usr/bin/env %(python)s
+import os.path
+import string
+import sys
+fp = open(sys.argv[1], 'wb')
+args = [os.path.split(sys.argv[0])[1]] + sys.argv[1:]
+fp.write(string.join(args) + '\\\\n' + '%(extra)s')
+for infile in sys.argv[2:]:
+ fp.write(open(infile, 'rb').read())
+fp.close()
+''')
+os.chmod(sys.argv[1], 0755)
+
+"""
+
+extra = ''
+test.write('generate_build_py.py', generate_build_py_py_contents % locals())
+
+test.write('SConstruct', """
+generate = Builder(action = r'%(_python_)s $GENERATE $TARGET')
+build = Builder(action = r'$BUILD_PY $TARGET $SOURCES')
+env = Environment(BUILDERS = {
+ 'GenerateBuild' : generate,
+ 'BuildFile' : build,
+ },
+ GENERATE = 'generate_build_py.py',
+ BUILD_PY = 'build.py',
+ )
+env.PrependENVPath('PATH', '.')
+env.PrependENVPath('PATHEXT', '.PY')
+env0 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 0)
+env1 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 1)
+envNone = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = None)
+envFalse = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = False)
+envTrue = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = True)
+
+build_py = env.GenerateBuild('${BUILD_PY}', [])
+AlwaysBuild(build_py)
+
+env.BuildFile('file.out', 'file.in')
+env0.BuildFile('file0.out', 'file.in')
+env1.BuildFile('file1.out', 'file.in')
+envNone.BuildFile('fileNone.out', 'file.in')
+envFalse.BuildFile('fileFalse.out', 'file.in')
+envTrue.BuildFile('fileTrue.out', 'file.in')
+""" % locals())
+
+
+
+test.write('file.in', "file.in\n")
+
+test.run(arguments = '--tree=all .')
+
+expect_none = 'build.py %s file.in\nfile.in\n'
+
+test.must_match('file.out', expect_none % 'file.out')
+test.must_match('file0.out', expect_none % 'file0.out')
+test.must_match('file1.out', expect_none % 'file1.out')
+test.must_match('fileNone.out', expect_none % 'fileNone.out')
+test.must_match('fileFalse.out', expect_none % 'fileFalse.out')
+test.must_match('fileTrue.out', expect_none % 'fileTrue.out')
+
+
+
+extra = 'xyzzy\\\\n'
+test.write('generate_build_py.py', generate_build_py_py_contents % locals())
+
+test.run(arguments = '--tree=all .')
+
+expect_extra = 'build.py %s file.in\nxyzzy\nfile.in\n'
+
+test.must_match('file.out', expect_extra % 'file.out')
+test.must_match('file0.out', expect_none % 'file0.out')
+test.must_match('file1.out', expect_extra % 'file1.out')
+test.must_match('fileNone.out', expect_none % 'fileNone.out')
+test.must_match('fileFalse.out', expect_none % 'fileFalse.out')
+test.must_match('fileTrue.out', expect_extra % 'fileTrue.out')
+
+
+test.pass_test()
diff --git a/test/implicit/asynchronous-modification.py b/test/implicit/asynchronous-modification.py
new file mode 100644
index 0000000..d10f823
--- /dev/null
+++ b/test/implicit/asynchronous-modification.py
@@ -0,0 +1,89 @@
+#!/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 expected behavior when an implicit dependency is modified
+asynchronously (that is, mid-build and without our knowledge).
+
+Test case courtesy Greg Noel.
+"""
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+test.write(['SConstruct'], """\
+import SCons.Defaults
+env = Environment()
+env['BUILDERS']['C'] = Builder(action = Copy('$TARGET', '$SOURCE'),
+ source_scanner = SCons.Defaults.CScan)
+env['BUILDERS']['Mod'] = Builder(action = r'%(_python_)s mod.py')
+Alias('seq', env.C('one.c'))
+Alias('seq', env.Mod('mod', 'mod.py'))
+Alias('seq', env.C('two.c'))
+Default('seq')
+""" % locals())
+
+test.write(['hdr.h'], """\
+/* empty header */
+""")
+
+test.write(['mod.py'], """\
+open('mod', 'w').write(open('mod.py', 'r').read())
+open('hdr.h', 'w').write("/* modified */\\n")
+""")
+
+test.write(['one.c'], """\
+#include "hdr.h"
+""")
+
+test.write(['two.c'], """\
+#include "hdr.h"
+""")
+
+# The first run builds the file 'one', then runs the 'mod' script
+# (which update modifies the 'hdr.h' file) then builds the file 'two'.
+test.run(arguments = 'seq')
+
+# The 'hdr.h' file had its original contents when 'one' was built,
+# and modified contents when 'two' was built. Because we took a
+# look at 'hdr.h' once, up front, we think both files are out of
+# date and will rebuild both (even though 'two' is really up to date).
+#
+# A future enhancement might add some sort of verification mode that
+# would examine 'hdr.h' again when 'two' was built, thereby avoiding
+# the unnecessary rebuild. In that case, the second line below
+# will need to change to "test.up_to_date(...)".
+test.not_up_to_date(arguments = 'one')
+test.not_up_to_date(arguments = 'two')
+
+# Regardless of what happened on the middle run(s), both files should
+# be up to date now.
+test.up_to_date(arguments = 'seq')
+
+test.pass_test()
diff --git a/test/changed-node.py b/test/implicit/changed-node.py
index 99a16ac..99a16ac 100644
--- a/test/changed-node.py
+++ b/test/implicit/changed-node.py
diff --git a/test/option-u.py b/test/option-u.py
index 9b5e88c..439daa2 100644
--- a/test/option-u.py
+++ b/test/option-u.py
@@ -73,7 +73,6 @@ env.Cat(target = 'f4a.out', source = 'f4a.in')
f4b_in = File('dir/f4b.in')
f4b_in.exists()
f4b_in.is_derived()
-f4b_in.is_pseudo_derived()
env.Cat(target = 'dir/f4b.out', source = f4b_in)
""")
diff --git a/test/option/debug-memoizer.py b/test/option/debug-memoizer.py
index 33f0f4d..8c8b2cf 100644
--- a/test/option/debug-memoizer.py
+++ b/test/option/debug-memoizer.py
@@ -69,7 +69,6 @@ expect = [
"Base.stat()",
"Dir.srcdir_list()",
"File.exists()",
- "FS._doLookup()",
"Node._children_get()",
]
diff --git a/test/option/debug-stree.py b/test/option/debug-stree.py
index 21ca386..d25b7fa 100644
--- a/test/option/debug-stree.py
+++ b/test/option/debug-stree.py
@@ -37,6 +37,10 @@ import time
test = TestSCons.TestSCons()
+CC = test.detect('CC')
+LINK = test.detect('LINK')
+if LINK is None: LINK = CC
+
test.write('SConstruct', """
env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx')
env.Program('foo', Split('foo.c bar.c'))
@@ -75,14 +79,17 @@ test.write('bar.h', """
stree = """
[E B C ]+-foo.xxx
[E B C ] +-foo.ooo
-[E ] | +-foo.c
-[E ] | +-foo.h
-[E ] | +-bar.h
+[E C ] | +-foo.c
+[E C ] | +-foo.h
+[E C ] | +-bar.h
+[E C ] | +-%(CC)s
[E B C ] +-bar.ooo
-[E ] +-bar.c
-[E ] +-bar.h
-[E ] +-foo.h
-"""
+[E C ] | +-bar.c
+[E C ] | +-bar.h
+[E C ] | +-foo.h
+[E C ] | +-%(CC)s
+[E C ] +-%(LINK)s
+""" % locals()
test.run(arguments = "--debug=stree foo.xxx")
test.fail_test(string.find(test.stdout(), stree) == -1)
@@ -101,14 +108,17 @@ stree2 = """
[ B ]+-foo.xxx
[ B ] +-foo.ooo
-[E ] | +-foo.c
-[E ] | +-foo.h
-[E ] | +-bar.h
+[E C ] | +-foo.c
+[E C ] | +-foo.h
+[E C ] | +-bar.h
+[E C ] | +-%(CC)s
[ B ] +-bar.ooo
-[E ] +-bar.c
-[E ] +-bar.h
-[E ] +-foo.h
-"""
+[E C ] | +-bar.c
+[E C ] | +-bar.h
+[E C ] | +-foo.h
+[E C ] | +-%(CC)s
+[E C ] +-%(LINK)s
+""" % locals()
test.run(arguments = '-c foo.xxx')
diff --git a/test/option/debug-time.py b/test/option/debug-time.py
index e8873cf..8a975a3 100644
--- a/test/option/debug-time.py
+++ b/test/option/debug-time.py
@@ -64,6 +64,12 @@ test.write('f4.in', "f4.in\n")
+# Before anything else, make sure we get valid --debug=time results
+# when just running the help option.
+test.run(arguments = "-h --debug=time")
+
+
+
def num(s, match):
return float(re.search(match, s).group(1))
diff --git a/test/option/debug-tree.py b/test/option/debug-tree.py
index 4f025c2..09cdffb 100644
--- a/test/option/debug-tree.py
+++ b/test/option/debug-tree.py
@@ -37,6 +37,10 @@ import time
test = TestSCons.TestSCons()
+CC = test.detect('CC')
+LINK = test.detect('LINK')
+if LINK is None: LINK = CC
+
test.write('SConstruct', """
env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx')
env.Program('Foo', Split('Foo.c Bar.c'))
@@ -82,40 +86,57 @@ tree1 = """
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Bar.ooo
- +-Bar.c
- +-Bar.h
- +-Foo.h
-"""
+ | +-Bar.c
+ | +-Bar.h
+ | +-Foo.h
+ | +-%(CC)s
+ +-%(LINK)s
+""" % locals()
test.run(arguments = "--debug=tree Foo.xxx")
-test.fail_test(string.find(test.stdout(), tree1) == -1)
+if string.find(test.stdout(), tree1) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
tree2 = """
+-.
+-Bar.c
+ +-Bar.h
+-Bar.ooo
| +-Bar.c
| +-Bar.h
| +-Foo.h
+ | +-%(CC)s
+-Foo.c
+ +-Foo.h
+-Foo.ooo
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Foo.xxx
| +-Foo.ooo
| | +-Foo.c
| | +-Foo.h
| | +-Bar.h
+ | | +-%(CC)s
| +-Bar.ooo
- | +-Bar.c
- | +-Bar.h
- | +-Foo.h
+ | | +-Bar.c
+ | | +-Bar.h
+ | | +-Foo.h
+ | | +-%(CC)s
+ | +-%(LINK)s
+-SConstruct
-"""
+""" % locals()
+
test.run(arguments = "--debug=tree .")
-test.fail_test(string.find(test.stdout(), tree2) == -1)
+if string.find(test.stdout(), tree2) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
# Make sure we print the debug stuff even if there's a build failure.
test.write('Bar.h', """
@@ -129,6 +150,9 @@ THIS SHOULD CAUSE A BUILD FAILURE
test.run(arguments = "--debug=tree Foo.xxx",
status = 2,
stderr = None)
-test.fail_test(string.find(test.stdout(), tree1) == -1)
+if string.find(test.stdout(), tree1) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
test.pass_test()
diff --git a/test/option/taskmastertrace.py b/test/option/taskmastertrace.py
index 30faced..3139504 100644
--- a/test/option/taskmastertrace.py
+++ b/test/option/taskmastertrace.py
@@ -34,29 +34,35 @@ test = TestSCons.TestSCons()
test.write('SConstruct', """
env = Environment()
-env.Command('file.out', 'file.mid', Copy('$TARGET', '$SOURCE'))
-env.Command('file.mid', 'file.in', Copy('$TARGET', '$SOURCE'))
+
+# We name the files 'Tfile' so that they will sort after the SConstruct
+# file regardless of whether the test is being run on a case-sensitive
+# or case-insensitive system.
+
+env.Command('Tfile.out', 'Tfile.mid', Copy('$TARGET', '$SOURCE'))
+env.Command('Tfile.mid', 'Tfile.in', Copy('$TARGET', '$SOURCE'))
""")
-test.write('file.in', "file.in\n")
+test.write('Tfile.in', "Tfile.in\n")
expect_stdout = test.wrap_stdout("""\
Taskmaster: '.': children:
- ['SConstruct', 'file.in', 'file.mid', 'file.out']
- waiting on unstarted children:
- ['file.mid', 'file.out']
-Taskmaster: 'file.mid': children:
- ['file.in']
- evaluating file.mid
-Copy("file.mid", "file.in")
-Taskmaster: 'file.out': children:
- ['file.mid']
- evaluating file.out
-Copy("file.out", "file.mid")
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
+ waiting on unfinished children:
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
+Taskmaster: 'SConstruct': evaluating SConstruct
+Taskmaster: 'Tfile.in': evaluating Tfile.in
+Taskmaster: 'Tfile.mid': children:
+ ['Tfile.in']
+ evaluating Tfile.mid
+Copy("Tfile.mid", "Tfile.in")
+Taskmaster: 'Tfile.out': children:
+ ['Tfile.mid']
+ evaluating Tfile.out
+Copy("Tfile.out", "Tfile.mid")
Taskmaster: '.': children:
- ['SConstruct', 'file.in', 'file.mid', 'file.out']
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
evaluating .
-Taskmaster: '.': already handled (executed)
""")
test.run(arguments='--taskmastertrace=- .', stdout=expect_stdout)
@@ -68,27 +74,28 @@ test.run(arguments='-c .')
expect_stdout = test.wrap_stdout("""\
-Copy("file.mid", "file.in")
-Copy("file.out", "file.mid")
+Copy("Tfile.mid", "Tfile.in")
+Copy("Tfile.out", "Tfile.mid")
""")
test.run(arguments='--taskmastertrace=trace.out .', stdout=expect_stdout)
expect_trace = """\
Taskmaster: '.': children:
- ['SConstruct', 'file.in', 'file.mid', 'file.out']
- waiting on unstarted children:
- ['file.mid', 'file.out']
-Taskmaster: 'file.mid': children:
- ['file.in']
- evaluating file.mid
-Taskmaster: 'file.out': children:
- ['file.mid']
- evaluating file.out
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
+ waiting on unfinished children:
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
+Taskmaster: 'SConstruct': evaluating SConstruct
+Taskmaster: 'Tfile.in': evaluating Tfile.in
+Taskmaster: 'Tfile.mid': children:
+ ['Tfile.in']
+ evaluating Tfile.mid
+Taskmaster: 'Tfile.out': children:
+ ['Tfile.mid']
+ evaluating Tfile.out
Taskmaster: '.': children:
- ['SConstruct', 'file.in', 'file.mid', 'file.out']
+ ['SConstruct', 'Tfile.in', 'Tfile.mid', 'Tfile.out']
evaluating .
-Taskmaster: '.': already handled (executed)
"""
test.must_match('trace.out', expect_trace)
diff --git a/test/option/tree-all.py b/test/option/tree-all.py
index ec7c7d8..7940d47 100644
--- a/test/option/tree-all.py
+++ b/test/option/tree-all.py
@@ -37,6 +37,10 @@ import time
test = TestSCons.TestSCons()
+CC = test.detect('CC')
+LINK = test.detect('LINK')
+if LINK is None: LINK = CC
+
test.write('SConstruct', """
env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx')
env.Program('Foo', Split('Foo.c Bar.c'))
@@ -82,65 +86,92 @@ tree1 = """
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Bar.ooo
- +-Bar.c
- +-Bar.h
- +-Foo.h
-"""
+ | +-Bar.c
+ | +-Bar.h
+ | +-Foo.h
+ | +-%(CC)s
+ +-%(LINK)s
+""" % locals()
test.run(arguments = "--tree=all Foo.xxx")
-test.fail_test(string.find(test.stdout(), tree1) == -1)
+if string.find(test.stdout(), tree1) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
tree2 = """
+-.
+-Bar.c
+ +-Bar.h
+-Bar.ooo
| +-Bar.c
| +-Bar.h
| +-Foo.h
+ | +-%(CC)s
+-Foo.c
+ +-Foo.h
+-Foo.ooo
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Foo.xxx
| +-Foo.ooo
| | +-Foo.c
| | +-Foo.h
| | +-Bar.h
+ | | +-%(CC)s
| +-Bar.ooo
- | +-Bar.c
- | +-Bar.h
- | +-Foo.h
+ | | +-Bar.c
+ | | +-Bar.h
+ | | +-Foo.h
+ | | +-%(CC)s
+ | +-%(LINK)s
+-SConstruct
-"""
+""" % locals()
test.run(arguments = "--tree=all .")
-test.fail_test(string.find(test.stdout(), tree2) == -1)
+if string.find(test.stdout(), tree2) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
tree3 = """
+-.
+-Bar.c
+ +-Bar.h
+-Bar.ooo
| +-Bar.c
| +-Bar.h
| +-Foo.h
+ | +-%(CC)s
+-Foo.c
+ +-Foo.h
+-Foo.ooo
| +-Foo.c
| +-Foo.h
| +-Bar.h
+ | +-%(CC)s
+-Foo.xxx
| +-[Foo.ooo]
| +-[Bar.ooo]
+ | +-%(LINK)s
+-SConstruct
-"""
+""" % locals()
test.run(arguments = "--tree=all,prune .")
-test.fail_test(string.find(test.stdout(), tree3) == -1)
+if string.find(test.stdout(), tree3) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
test.run(arguments = "--tree=prune .")
-test.fail_test(string.find(test.stdout(), tree3) == -1)
+if string.find(test.stdout(), tree3) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
tree4 = """
E = exists
@@ -156,22 +187,31 @@ tree4 = """
[ B ]+-Foo.xxx
[ B ] +-Foo.ooo
-[E ] | +-Foo.c
-[E ] | +-Foo.h
-[E ] | +-Bar.h
+[E C ] | +-Foo.c
+[E C ] | +-Foo.h
+[E C ] | +-Bar.h
+[E C ] | +-%(CC)s
[ B ] +-Bar.ooo
-[E ] +-Bar.c
-[E ] +-Bar.h
-[E ] +-Foo.h
-"""
+[E C ] | +-Bar.c
+[E C ] | +-Bar.h
+[E C ] | +-Foo.h
+[E C ] | +-%(CC)s
+[E C ] +-%(LINK)s
+""" % locals()
test.run(arguments = '-c Foo.xxx')
test.run(arguments = "--no-exec --tree=all,status Foo.xxx")
-test.fail_test(string.find(test.stdout(), tree4) == -1)
+if string.find(test.stdout(), tree4) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
test.run(arguments = "--no-exec --tree=status Foo.xxx")
-test.fail_test(string.find(test.stdout(), tree4) == -1)
+if string.find(test.stdout(), tree4) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
# Make sure we print the debug stuff even if there's a build failure.
test.write('Bar.h', """
@@ -185,6 +225,9 @@ THIS SHOULD CAUSE A BUILD FAILURE
test.run(arguments = "--tree=all Foo.xxx",
status = 2,
stderr = None)
-test.fail_test(string.find(test.stdout(), tree1) == -1)
+if string.find(test.stdout(), tree1) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
test.pass_test()
diff --git a/test/option/tree-lib.py b/test/option/tree-lib.py
new file mode 100644
index 0000000..fc29d50
--- /dev/null
+++ b/test/option/tree-lib.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Make sure that --tree=derived output with a library dependency shows
+the dependency on the library. (On earlier versions of the Microsoft
+toolchain this wouldn't show up unless the library already existed
+on disk.)
+
+Issue 1363: http://scons.tigris.org/issues/show_bug.cgi?id=1363
+"""
+
+import string
+import sys
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+env = Environment(LIBPREFIX='',
+ LIBSUFFIX='.lib',
+ OBJSUFFIX='.obj',
+ EXESUFFIX='.exe')
+env.AppendENVPath('PATH', '.')
+l = env.Library( 'util.lib', 'util.c' )
+p = env.Program( 'test.exe', 'main.c', LIBS=l )
+env.Command( 'foo.h', p, '$SOURCE > $TARGET')
+""")
+
+test.write('main.c', """\
+#include <stdlib.h>
+#include <stdio.h>
+int
+main(int argc, char *argv)
+{
+ printf("#define FOO_H \\"foo.h\\"\\n");
+ return (0);
+}
+""")
+
+test.write('util.c', """\
+void
+util(void)
+{
+ ;
+}
+""")
+
+expect = """
+ +-test.exe
+ +-main.obj
+ +-util.lib
+ +-util.obj
+"""
+
+test.run(arguments = '--tree=derived foo.h')
+if string.find(test.stdout(), expect) == -1:
+ sys.stdout.write('Did not find expected tree in the following output:\n')
+ sys.stdout.write(test.stdout())
+ test.fail_test()
+
+test.up_to_date(arguments = 'foo.h')
+
+test.pass_test()
diff --git a/test/packaging/convenience-functions.py b/test/packaging/convenience-functions.py
new file mode 100644
index 0000000..6eae270
--- /dev/null
+++ b/test/packaging/convenience-functions.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the FindInstalledFiles() and the FindSourceFiles() functions.
+"""
+
+import os.path
+import string
+import TestSCons
+
+python = TestSCons.python
+test = TestSCons.TestSCons()
+
+test.write( "f1", "" )
+test.write( "f2", "" )
+test.write( "f3", "" )
+
+test.write( 'SConstruct', r"""
+env = Environment(tools=['default', 'packaging'])
+prog = env.Install( 'bin/', ["f1", "f2"] )
+env.File( "f3" )
+
+src_files = map(str, env.FindSourceFiles())
+oth_files = map(str, env.FindInstalledFiles())
+src_files.sort()
+oth_files.sort()
+
+print src_files
+print oth_files
+""")
+
+bin_f1 = os.path.join('bin', 'f1')
+bin_f2 = os.path.join('bin', 'f2')
+
+bin__f1 = string.replace(bin_f1, '\\', '\\\\')
+bin__f2 = string.replace(bin_f2, '\\', '\\\\')
+
+expect_read = """\
+['SConstruct', 'f1', 'f2', 'f3']
+['%(bin__f1)s', '%(bin__f2)s']
+""" % locals()
+
+expect_build = """\
+Install file: "f1" as "%(bin_f1)s"
+Install file: "f2" as "%(bin_f2)s"
+""" % locals()
+
+expected = test.wrap_stdout(read_str = expect_read, build_str = expect_build)
+
+test.run(stdout=expected)
+
+test.pass_test()
diff --git a/test/packaging/msi/explicit-target.py b/test/packaging/msi/explicit-target.py
new file mode 100644
index 0000000..745f0c1
--- /dev/null
+++ b/test/packaging/msi/explicit-target.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the ability to use a explicit target package name and the use
+of FindInstalledFiles() in conjuction with .msi packages.
+"""
+
+import os
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+try:
+ from xml.dom.minidom import *
+except ImportError:
+ test.skip_test('Canoot import xml.dom.minidom skipping test\n')
+
+wix = test.Environment().WhereIs('candle')
+
+if not wix:
+ test.skip_test("No 'candle' found; skipping test\n")
+
+#
+# build with minimal tag set and test for the given package meta-data
+#
+test.write( 'file1.exe', "file1" )
+test.write( 'file2.exe', "file2" )
+
+test.write('SConstruct', """
+import os
+
+env = Environment(tools=['default', 'packaging'])
+
+f1 = env.Install( '/usr/' , 'file1.exe' )
+f2 = env.Install( '/usr/' , 'file2.exe' )
+
+env.Alias( 'install', [ f1, f2 ] )
+
+env.Package( NAME = 'foo',
+ VERSION = '1.2',
+ PACKAGETYPE = 'msi',
+ SUMMARY = 'balalalalal',
+ DESCRIPTION = 'this should be reallly really long',
+ VENDOR = 'Nanosoft_2000',
+ source = env.FindInstalledFiles(),
+ target = "mypackage.msi",
+ )
+""")
+
+test.run(arguments='', stderr = None)
+
+test.must_exist( 'foo-1.2.wxs' )
+test.must_exist( 'foo-1.2.msi' )
+
+dom = parse( test.workpath( 'foo-1.2.wxs' ) )
+Product = dom.getElementsByTagName( 'Product' )[0]
+Package = dom.getElementsByTagName( 'Package' )[0]
+
+test.fail_test( not Product.attributes['Manufacturer'].value == 'Nanosoft_2000' )
+test.fail_test( not Product.attributes['Version'].value == '1.2' )
+test.fail_test( not Product.attributes['Name'].value == 'foo' )
+
+test.fail_test( not Package.attributes['Description'].value == 'balalalalal' )
+test.fail_test( not Package.attributes['Comments'].value == 'this should be reallly really long' )
+
+test.pass_test()
diff --git a/test/packaging/multiple-packages-at-once.py b/test/packaging/multiple-packages-at-once.py
new file mode 100644
index 0000000..3151c05
--- /dev/null
+++ b/test/packaging/multiple-packages-at-once.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+See if the packaging tool is able to build multiple packages at once.
+
+TODO: test if the packages are clean versions (i.e. do not contain files
+ added by different packager runs)
+"""
+
+import TestSCons
+
+python = TestSCons.python
+
+test = TestSCons.TestSCons()
+
+zip = test.detect('ZIP', 'zip')
+
+if not zip:
+ test.skip_test('zip not found, skipping test\n')
+
+test.subdir('src')
+
+test.write( [ 'src', 'main.c' ], r"""
+int main( int argc, char* argv[] )
+{
+ return 0;
+}
+""")
+
+test.write('SConstruct', """
+Program( 'src/main.c' )
+env=Environment(tools=['default', 'packaging'])
+env.Package( PACKAGETYPE = ['src_zip', 'src_targz'],
+ target = ['src.zip', 'src.tar.gz'],
+ PACKAGEROOT = 'test',
+ source = [ 'src/main.c', 'SConstruct' ] )
+""")
+
+test.run(arguments='', stderr = None)
+
+test.must_exist( 'src.zip' )
+test.must_exist( 'src.tar.gz' )
+
+test.write('SConstruct', """
+Program( 'src/main.c' )
+env=Environment(tools=['default', 'packaging'])
+env.Package( PACKAGETYPE = ['src_zip', 'src_targz'],
+ NAME = "src", VERSION = "1.0",
+ PACKAGEROOT = 'test',
+ source = [ 'src/main.c', 'SConstruct' ] )
+""")
+
+test.run(arguments='', stderr = None)
+
+test.must_exist( 'src-1.0.zip' )
+test.must_exist( 'src-1.0.tar.gz' )
+
+test.pass_test()
diff --git a/test/packaging/multiple-subdirs.py b/test/packaging/multiple-subdirs.py
new file mode 100644
index 0000000..80758ab
--- /dev/null
+++ b/test/packaging/multiple-subdirs.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Verify that we can build packages in different subdirectories.
+
+Test case courtesy Andrew Smith.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+tar = test.detect('TAR', 'tar')
+
+if not tar:
+ test.skip_test('No TAR executable found; skipping test\n')
+
+test.subdir('one', 'two', 'three')
+
+test.write('SConstruct', """\
+env = Environment(tools=['default', 'packaging'])
+Export('env')
+SConscript(dirs = ['one', 'two', 'three'])
+""")
+
+SConscript_template = """\
+Import('*')
+
+files = env.Install('/usr/bin', '%s.sh')
+
+pkg = env.Package(NAME = '%s',
+ VERSION = '1.0.0',
+ PACKAGETYPE = 'targz',
+ source = [files]
+ )
+"""
+
+test.write(['one', 'SConscript'], SConscript_template % ('one', 'one'))
+test.write(['two', 'SConscript'], SConscript_template % ('two', 'two'))
+test.write(['three', 'SConscript'], SConscript_template % ('three', 'three'))
+
+test.write(['one', 'one.sh'], "one/one.sh\n")
+test.write(['two', 'two.sh'], "two/two.sh\n")
+test.write(['three', 'three.sh'], "three/three.sh\n")
+
+test.run(arguments = '.')
+
+test.must_match(['one', 'one-1.0.0', 'usr', 'bin', 'one.sh'], "one/one.sh\n")
+test.must_match(['two', 'two-1.0.0', 'usr', 'bin', 'two.sh'], "two/two.sh\n")
+test.must_match(['three', 'three-1.0.0', 'usr', 'bin', 'three.sh'], "three/three.sh\n")
+
+test.must_exist(['one', 'one-1.0.0.tar.gz'])
+test.must_exist(['two', 'two-1.0.0.tar.gz'])
+test.must_exist(['three', 'three-1.0.0.tar.gz'])
+
+test.pass_test()
diff --git a/test/packaging/option--package-type.py b/test/packaging/option--package-type.py
index 00a569e..ce16e95 100644
--- a/test/packaging/option--package-type.py
+++ b/test/packaging/option--package-type.py
@@ -67,14 +67,21 @@ env.Package( NAME = 'foo',
)
""" % locals())
-test.run(arguments='package PACKAGETYPE=rpm', stderr = None)
-
src_rpm = 'foo-1.2.3-0.src.rpm'
machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine
+test.run(arguments='package PACKAGETYPE=rpm', stderr = None)
+
test.must_exist( src_rpm )
test.must_exist( machine_rpm )
+test.must_not_exist( 'bin/main.c' )
+test.must_not_exist( '/bin/main.c' )
+
+test.run(arguments='-c package PACKAGETYPE=rpm', stderr = None)
+test.run(arguments='package --package-type=rpm', stderr = None)
+test.must_exist( src_rpm )
+test.must_exist( machine_rpm )
test.must_not_exist( 'bin/main.c' )
test.must_not_exist( '/bin/main.c' )
diff --git a/test/packaging/place-files-in-subdirectory.py b/test/packaging/place-files-in-subdirectory.py
index d9758a1..66bdd53 100644
--- a/test/packaging/place-files-in-subdirectory.py
+++ b/test/packaging/place-files-in-subdirectory.py
@@ -38,7 +38,7 @@ test = TestSCons.TestSCons()
tar = test.detect('TAR', 'tar')
if not tar:
- test.skipt_test('tar not found, skipping test\n')
+ test.skip_test('tar not found, skipping test\n')
#
# TEST: subdir creation and file copying
diff --git a/test/packaging/rpm/cleanup.py b/test/packaging/rpm/cleanup.py
index 5472fbb..11f6645 100644
--- a/test/packaging/rpm/cleanup.py
+++ b/test/packaging/rpm/cleanup.py
@@ -83,9 +83,11 @@ env.Alias( 'install', prog )
""" % locals())
# first run: build the package
-# second run: test if the intermediate files have been cleaned
-test.run( arguments='' )
-test.run( arguments='-c' )
+# second run: make sure everything is up-to-date (sanity check)
+# third run: test if the intermediate files have been cleaned
+test.run( arguments='.' )
+test.up_to_date( arguments='.' )
+test.run( arguments='-c .' )
src_rpm = 'foo-1.2.3-0.src.rpm'
machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine
diff --git a/test/packaging/rpm/explicit-target.py b/test/packaging/rpm/explicit-target.py
new file mode 100644
index 0000000..12a6c6c
--- /dev/null
+++ b/test/packaging/rpm/explicit-target.py
@@ -0,0 +1,95 @@
+#!/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 the ability to create a rpm package from a explicit target name.
+"""
+
+import os
+import TestSCons
+
+machine = TestSCons.machine
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+scons = test.program
+
+rpm = test.Environment().WhereIs('rpm')
+
+if not rpm:
+ test.skip_test('rpm not found, skipping test\n')
+
+rpm_build_root = test.workpath('rpm_build_root')
+
+test.subdir('src')
+
+test.write( [ 'src', 'main.c' ], r"""
+int main( int argc, char* argv[] )
+{
+ return 0;
+}
+""")
+
+test.write('SConstruct', """
+import os
+
+env=Environment(tools=['default', 'packaging'])
+
+env.Prepend(RPM = 'TAR_OPTIONS=--wildcards ')
+env.Append(RPMFLAGS = r' --buildroot %(rpm_build_root)s')
+
+prog = env.Install( '/bin/' , Program( 'src/main.c') )
+
+env.Alias( 'install', prog )
+
+env.Package( NAME = 'foo',
+ VERSION = '1.2.3',
+ PACKAGEVERSION = 0,
+ PACKAGETYPE = 'rpm',
+ LICENSE = 'gpl',
+ SUMMARY = 'balalalalal',
+ X_RPM_GROUP = 'Application/fu',
+ X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"',
+ DESCRIPTION = 'this should be really really long',
+ source = [ prog ],
+ target = "my_rpm_package.rpm",
+ SOURCE_URL = 'http://foo.org/foo-1.2.3.tar.gz'
+ )
+""" % locals())
+
+test.run(arguments='', stderr = None)
+
+src_rpm = 'foo-1.2.3-0.src.rpm'
+machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine
+
+test.must_exist( machine_rpm )
+test.must_exist( src_rpm )
+test.must_not_exist( 'bin/main' )
+test.fail_test( not os.popen('rpm -qpl %s' % machine_rpm).read()=='/bin/main\n')
+test.fail_test( not os.popen('rpm -qpl %s' % src_rpm).read()=='foo-1.2.3.spec\nfoo-1.2.3.tar.gz\n')
+
+test.pass_test()
diff --git a/test/packaging/rpm/internationalization.py b/test/packaging/rpm/internationalization.py
index af0bc75..24d8ddd 100644
--- a/test/packaging/rpm/internationalization.py
+++ b/test/packaging/rpm/internationalization.py
@@ -104,12 +104,10 @@ test.must_not_exist( 'bin/main' )
cmd = 'rpm -qp --queryformat \'%%{GROUP}-%%{SUMMARY}-%%{DESCRIPTION}\' %s'
-os.environ['LC_ALL'] = 'de_DE.utf8'
os.environ['LANGUAGE'] = 'de'
out = os.popen( cmd % test.workpath(machine_rpm) ).read()
test.fail_test( out != 'Applikation/büro-hallo-das sollte wirklich lang sein' )
-os.environ['LC_ALL'] = 'fr_FR.utf8'
os.environ['LANGUAGE'] = 'fr'
out = os.popen( cmd % test.workpath(machine_rpm) ).read()
test.fail_test( out != 'Application/bureau-bonjour-ceci devrait être vraiment long' )
diff --git a/test/packaging/rpm/multipackage.py b/test/packaging/rpm/multipackage.py
new file mode 100644
index 0000000..5b85db3
--- /dev/null
+++ b/test/packaging/rpm/multipackage.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__"
+
+"""
+Test the ability to create more than rpm file with different package root
+from one SCons environment.
+"""
+
+import os
+import TestSCons
+
+machine = TestSCons.machine
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+scons = test.program
+
+rpm = test.Environment().WhereIs('rpm')
+
+if not rpm:
+ test.skip_test('rpm not found, skipping test\n')
+
+rpm_build_root = test.workpath('rpm_build_root')
+
+test.subdir('src')
+
+test.write( [ 'src', 'main.c' ], r"""
+int main( int argc, char* argv[] )
+{
+ return 0;
+}
+""")
+
+test.write('SConstruct', """
+import os
+
+env=Environment(tools=['default', 'packaging'])
+
+env.Prepend(RPM = 'TAR_OPTIONS=--wildcards ')
+env.Append(RPMFLAGS = r' --buildroot %(rpm_build_root)s')
+
+prog = env.Install( '/bin/' , Program( 'src/main.c') )
+
+env.Package( NAME = 'foo',
+ VERSION = '1.2.3',
+ PACKAGEVERSION = 0,
+ PACKAGETYPE = 'rpm',
+ LICENSE = 'gpl',
+ SUMMARY = 'balalalalal',
+ X_RPM_GROUP = 'Application/fu',
+ X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"',
+ DESCRIPTION = 'this should be really really long',
+ source = [ prog ],
+ SOURCE_URL = 'http://foo.org/foo-1.2.3.tar.gz'
+ )
+
+env.Package( NAME = 'foo2',
+ VERSION = '1.2.3',
+ PACKAGEVERSION = 0,
+ PACKAGETYPE = 'rpm',
+ LICENSE = 'gpl',
+ SUMMARY = 'balalalalal',
+ X_RPM_GROUP = 'Application/fu',
+ X_RPM_INSTALL = r'%(_python_)s %(scons)s --debug=tree --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"',
+ DESCRIPTION = 'this should be really really long',
+ source = [ prog ],
+ )
+
+
+
+env.Alias( 'install', prog )
+""" % locals())
+
+test.run(arguments='', stderr = None)
+
+src_rpm = 'foo-1.2.3-0.src.rpm'
+machine_rpm = 'foo-1.2.3-0.%s.rpm' % machine
+src_rpm2 = 'foo2-1.2.3-0.src.rpm'
+machine_rpm2 = 'foo2-1.2.3-0.%s.rpm' % machine
+
+test.must_exist( machine_rpm )
+test.must_exist( src_rpm )
+
+test.must_exist( machine_rpm2 )
+test.must_exist( src_rpm2 )
+
+test.must_not_exist( 'bin/main' )
+test.fail_test( not os.popen('rpm -qpl %s' % machine_rpm).read()=='/bin/main\n')
+test.fail_test( not os.popen('rpm -qpl %s' % src_rpm).read()=='foo-1.2.3.spec\nfoo-1.2.3.tar.gz\n')
+
+test.pass_test()
diff --git a/test/packaging/strip-install-dir.py b/test/packaging/strip-install-dir.py
index 65b6a61..ec40220 100644
--- a/test/packaging/strip-install-dir.py
+++ b/test/packaging/strip-install-dir.py
@@ -34,6 +34,11 @@ python = TestSCons.python
test = TestSCons.TestSCons()
+tar = test.detect('TAR', 'tar')
+
+if not tar:
+ test.skip_test('tar not found, skipping test\n')
+
test.write( 'main.c', '' )
test.write('SConstruct', """
prog = Install( '/bin', 'main.c' )
diff --git a/test/option-q.py b/test/question/Configure.py
index 9b67d0a..aeaba8a 100644
--- a/test/option-q.py
+++ b/test/question/Configure.py
@@ -24,64 +24,25 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""
+Verify operation of the -q (--question) option in conjunction
+with Configure tests.
+
+(This was originally mostly copied and pasted from test/option-n.py.)
+"""
+
import os.path
import re
-import string
-import sys
import TestCmd
import TestSCons
-test = TestSCons.TestSCons()
-
-_python_ = TestSCons._python_
-
-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('SConstruct', """
-B = Builder(action=r'%(_python_)s build.py $TARGET $SOURCES')
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'aaa.out', source = 'aaa.in')
-env.B(target = 'bbb.out', source = 'bbb.in')
-""" % locals())
-
-test.write('aaa.in', "aaa.in\n")
-test.write('bbb.in', "bbb.in\n")
-
-test.run(arguments = '-q aaa.out', status = 1)
-
-test.fail_test(os.path.exists(test.workpath('aaa.out')))
-
-test.run(arguments = 'aaa.out')
-
-test.fail_test(test.read('aaa.out') != "aaa.in\n")
-
-test.run(arguments = '-q aaa.out', status = 0)
+test = TestSCons.TestSCons(match = TestCmd.match_re_dotall)
-test.run(arguments = '--question bbb.out', status = 1)
+test.write('aaa.in', 'Hello world\n')
-test.fail_test(os.path.exists(test.workpath('bbb.out')))
-
-test.run(arguments = 'bbb.out')
-
-test.fail_test(test.read('bbb.out') != "bbb.in\n")
-
-test.run(arguments = '--question bbb.out', status = 0)
-
-
-# test -q in conjunction with Configure Tests
-# mostly copy&paste from test/option-n.py
-test.subdir('configure')
-test.match_func = TestCmd.match_re_dotall
-test.write('configure/aaa.in', 'Hello world')
-test.write('configure/SConstruct',
-"""def userAction(target,source,env):
+test.write('SConstruct', """\
+def userAction(target,source,env):
import shutil
shutil.copyfile( str(source[0]), str(target[0]))
@@ -108,15 +69,16 @@ else:
env.B(target='aaa.out', source='aaa.in')
""")
+
# test that conf_dir isn't created and an error is raised
stderr=r"""
scons: \*\*\* Cannot create configure directory "config\.test" within a dry-run\.
File \S+, line \S+, in \S+
"""
-test.run(arguments="-q aaa.out",stderr=stderr,status=2,
- chdir=test.workpath("configure"))
-test.fail_test(os.path.exists(test.workpath("configure", "config.test")))
-test.fail_test(os.path.exists(test.workpath("configure", "config.log")))
+test.run(arguments="-q aaa.out",stderr=stderr,status=2)
+
+test.must_not_exist(test.workpath("config.test"))
+test.must_not_exist(test.workpath("config.log"))
# test that targets are not built, if conf_dir exists.
# verify that .cache and config.log are not created.
@@ -125,27 +87,28 @@ stderr=r"""
scons: \*\*\* Cannot update configure test "%s" within a dry-run\.
File \S+, line \S+, in \S+
""" % re.escape(os.path.join("config.test", "conftest_0.in"))
-test.subdir(['configure','config.test'])
-test.run(arguments="-q aaa.out",stderr=stderr,status=2,
- chdir=test.workpath("configure"))
-test.fail_test(os.path.exists(test.workpath("configure", "config.test",
- ".cache")))
-test.fail_test(os.path.exists(test.workpath("configure", "config.test",
- "conftest_0")))
-test.fail_test(os.path.exists(test.workpath("configure", "config.test",
- "conftest_0.in")))
-test.fail_test(os.path.exists(test.workpath("configure", "config.log")))
+
+test.subdir('config.test')
+
+test.run(arguments="-q aaa.out",stderr=stderr,status=2)
+
+test.must_not_exist(test.workpath("config.test", ".cache"))
+test.must_not_exist(test.workpath("config.test", "conftest_0"))
+test.must_not_exist(test.workpath("config.test", "conftest_0.in"))
+test.must_not_exist(test.workpath("config.log"))
# test that no error is raised, if all targets are up-to-date. In this
# case .cache and config.log shouldn't be created
stdout=test.wrap_stdout(build_str='cp aaa.in aaa.out\n',
read_str="""Executing Custom Test ... yes
""")
-test.run(stdout=stdout,arguments="aaa.out",status=0,chdir=test.workpath("configure"))
-log1_mtime = os.path.getmtime(test.workpath("configure","config.log"))
-test.run(arguments="-q aaa.out",status=0,
- chdir=test.workpath("configure"))
-log2_mtime = os.path.getmtime(test.workpath("configure","config.log"))
+
+test.run(stdout=stdout,arguments="aaa.out",status=0)
+
+log1_mtime = os.path.getmtime(test.workpath("config.log"))
+
+test.run(arguments="-q aaa.out",status=0)
+log2_mtime = os.path.getmtime(test.workpath("config.log"))
test.fail_test( log1_mtime != log2_mtime )
test.pass_test()
diff --git a/test/question/basic.py b/test/question/basic.py
new file mode 100644
index 0000000..dc07e48
--- /dev/null
+++ b/test/question/basic.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 basic operation of the -q (--question) option.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+_python_ = TestSCons._python_
+
+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('SConstruct', """
+B = Builder(action=r'%(_python_)s build.py $TARGET $SOURCES')
+env = Environment(BUILDERS = { 'B' : B })
+env.B(target = 'aaa.out', source = 'aaa.in')
+env.B(target = 'bbb.out', source = 'bbb.in')
+""" % locals())
+
+test.write('aaa.in', "aaa.in\n")
+test.write('bbb.in', "bbb.in\n")
+
+test.run(arguments = '-q aaa.out', status = 1)
+
+test.must_not_exist(test.workpath('aaa.out'))
+
+test.run(arguments = 'aaa.out')
+
+test.must_match('aaa.out', "aaa.in\n")
+
+test.run(arguments = '-q aaa.out', status = 0)
+
+test.run(arguments = '--question bbb.out', status = 1)
+
+test.must_not_exist(test.workpath('bbb.out'))
+
+test.run(arguments = 'bbb.out')
+
+test.must_match('bbb.out', "bbb.in\n")
+
+test.run(arguments = '--question bbb.out', status = 0)
+
+test.pass_test()
diff --git a/test/question/no-builder.py b/test/question/no-builder.py
new file mode 100644
index 0000000..d038724
--- /dev/null
+++ b/test/question/no-builder.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 operation of the -q (--question) option when a specified
+target has no builder.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+_python_ = TestSCons._python_
+
+test.write('SConstruct', """
+""")
+
+test.run(arguments = '-q no_such_target', status = 1)
+
+test.run(arguments = '--question no_such_target', status = 1)
+
+test.pass_test()
diff --git a/test/runtest/fallback.py b/test/runtest/fallback.py
index 90cd4f2..8b6ae42 100644
--- a/test/runtest/fallback.py
+++ b/test/runtest/fallback.py
@@ -68,12 +68,20 @@ if re.search('\s', python):
else:
expect_python = python
+def escape(s):
+ return string.replace(s, '\\', '\\\\')
+
+expect_python = escape(expect_python)
+expect_workpath_pass_py = escape(workpath_pass_py)
+expect_workpath_fail_py = escape(workpath_fail_py)
+expect_workpath_no_result_py = escape(workpath_no_result_py)
+
expect_stdout = """\
-%(expect_python)s -tt %(workpath_fail_py)s
+%(expect_python)s -tt %(expect_workpath_fail_py)s
FAILING TEST STDOUT
-%(expect_python)s -tt %(workpath_no_result_py)s
+%(expect_python)s -tt %(expect_workpath_no_result_py)s
NO RESULT TEST STDOUT
-%(expect_python)s -tt %(workpath_pass_py)s
+%(expect_python)s -tt %(expect_workpath_pass_py)s
PASSING TEST STDOUT
Failed the following test:
diff --git a/test/runtest/noqmtest.py b/test/runtest/noqmtest.py
index c442125..f2bf6eb 100644
--- a/test/runtest/noqmtest.py
+++ b/test/runtest/noqmtest.py
@@ -59,12 +59,20 @@ if re.search('\s', python):
else:
expect_python = python
+def escape(s):
+ return string.replace(s, '\\', '\\\\')
+
+expect_python = escape(expect_python)
+expect_workpath_pass_py = escape(workpath_pass_py)
+expect_workpath_fail_py = escape(workpath_fail_py)
+expect_workpath_no_result_py = escape(workpath_no_result_py)
+
expect_stdout = """\
-%(expect_python)s -tt %(workpath_fail_py)s
+%(expect_python)s -tt %(expect_workpath_fail_py)s
FAILING TEST STDOUT
-%(expect_python)s -tt %(workpath_no_result_py)s
+%(expect_python)s -tt %(expect_workpath_no_result_py)s
NO RESULT TEST STDOUT
-%(expect_python)s -tt %(workpath_pass_py)s
+%(expect_python)s -tt %(expect_workpath_pass_py)s
PASSING TEST STDOUT
Failed the following test:
diff --git a/test/runtest/python.py b/test/runtest/python.py
index 1af32dd..95b5f0f 100644
--- a/test/runtest/python.py
+++ b/test/runtest/python.py
@@ -46,17 +46,11 @@ head, dir = os.path.split(head)
mypython = os.path.join(head, dir, os.path.pardir, dir, python)
-if re.search('\s', mypython):
- _mypython_ = '"' + mypython + '"'
-else:
- _mypython_ = mypython
-
test.subdir('test')
test.write_passing_test(['test', 'pass.py'])
-# NOTE: The "test/fail.py : FAIL" and "test/pass.py : PASS" lines both
-# have spaces at the end.
+# NOTE: The "test/pass.py : PASS" line has spaces at the end.
expect = r"""qmtest.py run --output results.qmr --format none --result-stream="scons_tdb.AegisChangeStream" --context python="%(mypython)s" test
--- TEST RESULTS -------------------------------------------------------------
@@ -75,6 +69,6 @@ expect = r"""qmtest.py run --output results.qmr --format none --result-stream="s
1 (100%%) tests PASS
""" % locals()
-test.run(arguments = '-P %s test' % _mypython_, stdout = expect)
+test.run(arguments = ['-P', mypython, 'test'], stdout = expect)
test.pass_test()
diff --git a/test/sconsign/script/Configure.py b/test/sconsign/script/Configure.py
new file mode 100644
index 0000000..8e17e95
--- /dev/null
+++ b/test/sconsign/script/Configure.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 we can print .sconsign files with Configure context
+info in them (which have different BuildInfo entries).
+"""
+
+import os.path
+
+import TestSCons
+import TestSConsign
+
+_obj = TestSCons._obj
+
+test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+
+CC = test.detect('CC', norm=1)
+CC_dir, CC_file = os.path.split(CC)
+
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+_sconf_temp_conftest_0_c = '.sconf_temp/conftest_0.c'
+
+test.write('SConstruct', """
+env = Environment()
+import os
+env.AppendENVPath('PATH', os.environ['PATH'])
+conf = Configure(env)
+r1 = conf.CheckCHeader( 'math.h' )
+env = conf.Finish()
+""")
+
+test.run(arguments = '.')
+
+sig_re = r'[0-9a-fA-F]{32}'
+date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
+
+# Note: There's a space at the end of the '.*': line, because the
+# Value node being printed actually begins with a newline. It would
+# probably be good to change that to a repr() of the contents.
+expect = r"""=== .:
+SConstruct: None \d+ \d+
+=== .sconf_temp:
+conftest_0.c:
+ '.*':
+#include "math.h"
+
+
+ %(sig_re)s \[.*\]
+conftest_0%(_obj)s:
+ %(_sconf_temp_conftest_0_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+=== %(CC_dir)s:
+%(CC_file)s: %(sig_re)s \d+ \d+
+""" % locals()
+
+test.run_sconsign(arguments = ".sconsign",
+ stdout = expect)
+
+test.pass_test()
diff --git a/test/sconsign/script/SConsignFile.py b/test/sconsign/script/SConsignFile.py
index 2f5ddf3..99845e3 100644
--- a/test/sconsign/script/SConsignFile.py
+++ b/test/sconsign/script/SConsignFile.py
@@ -29,12 +29,30 @@ Verify that the sconsign script works with files generated when
using the signatures in an SConsignFile().
"""
+import os.path
+
import TestSConsign
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+CC = test.detect('CC', norm=1)
+CC_dir, CC_file = os.path.split(CC)
+LINK = test.detect('LINK', norm=1)
+if LINK is None: LINK = CC
+
test.subdir('sub1', 'sub2')
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+sub1_hello_c = 'sub1/hello.c'
+sub1_hello_obj = 'sub1/hello.obj'
+sub2_hello_c = 'sub2/hello.c'
+sub2_hello_obj = 'sub2/hello.obj'
+sub2_inc1_h = 'sub2/inc1.h'
+sub2_inc2_h = 'sub2/inc2.h'
+
test.write(['SConstruct'], """\
SConsignFile()
env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
@@ -79,182 +97,328 @@ test.write(['sub2', 'inc2.h'], r"""\
test.run(arguments = '--implicit-cache .')
+sig_re = r'[0-9a-fA-F]{32}'
+
test.run_sconsign(arguments = ".sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct: None \d+ \d+
+=== %(CC_dir)s:
+%(CC_file)s: %(sig_re)s \d+ \d+
=== sub1:
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
+hello.c: %(sig_re)s \d+ \d+
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
=== sub2:
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+hello.c: %(sig_re)s \d+ \d+
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub2_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+inc1.h: %(sig_re)s \d+ \d+
+inc2.h: %(sig_re)s \d+ \d+
+""" % locals())
test.run_sconsign(arguments = "--raw .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct: {'csig': None, 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+=== %(CC_dir)s:
+%(CC_file)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
=== sub1:
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
+hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub1_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub1_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
=== sub2:
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub2_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub2_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub2_inc1_h)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub2_inc2_h)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+inc1.h: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+inc2.h: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+""" % locals())
-test.run_sconsign(arguments = "-v .sconsign",
- stdout = """\
+expect = r"""=== .:
+SConstruct:
+ csig: None
+ timestamp: \d+
+ size: \d+
+=== %(CC_dir)s:
+%(CC_file)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
=== sub1:
+hello.c:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
hello.exe:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.obj: \S+
+ %(sub1_hello_obj)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(LINK)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
hello.obj:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.c: \S+
+ %(sub1_hello_c)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(CC)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
=== sub2:
+hello.c:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
hello.exe:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.obj: \S+
+ %(sub2_hello_obj)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(LINK)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
hello.obj:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+ %(sub2_hello_c)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(sub2_inc1_h)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(sub2_inc2_h)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(CC)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
+inc1.h:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+inc2.h:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+""" % locals()
-test.run_sconsign(arguments = "-b -v .sconsign",
- stdout = """\
-=== sub1:
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-=== sub2:
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-""")
+test.run_sconsign(arguments = "-v .sconsign", stdout=expect)
test.run_sconsign(arguments = "-c -v .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct:
+ csig: None
+=== %(CC_dir)s:
+%(CC_file)s:
+ csig: %(sig_re)s
=== sub1:
+hello.c:
+ csig: %(sig_re)s
hello.exe:
- csig: None
+ csig: %(sig_re)s
hello.obj:
- csig: None
+ csig: %(sig_re)s
=== sub2:
+hello.c:
+ csig: %(sig_re)s
hello.exe:
- csig: None
+ csig: %(sig_re)s
hello.obj:
- csig: None
-""")
+ csig: %(sig_re)s
+inc1.h:
+ csig: %(sig_re)s
+inc2.h:
+ csig: %(sig_re)s
+""" % locals())
test.run_sconsign(arguments = "-s -v .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct:
+ size: \d+
+=== %(CC_dir)s:
+%(CC_file)s:
+ size: \d+
=== sub1:
+hello.c:
+ size: \d+
hello.exe:
size: \d+
hello.obj:
size: \d+
=== sub2:
+hello.c:
+ size: \d+
hello.exe:
size: \d+
hello.obj:
size: \d+
-""")
+inc1.h:
+ size: \d+
+inc2.h:
+ size: \d+
+""" % locals())
test.run_sconsign(arguments = "-t -v .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+SConstruct:
+ timestamp: \d+
+=== %(CC_dir)s:
+%(CC_file)s:
+ timestamp: \d+
=== sub1:
+hello.c:
+ timestamp: \d+
hello.exe:
timestamp: \d+
hello.obj:
timestamp: \d+
=== sub2:
+hello.c:
+ timestamp: \d+
hello.exe:
timestamp: \d+
hello.obj:
timestamp: \d+
-""")
+inc1.h:
+ timestamp: \d+
+inc2.h:
+ timestamp: \d+
+""" % locals())
test.run_sconsign(arguments = "-e hello.obj .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+=== %(CC_dir)s:
=== sub1:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
=== sub2:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals(),
+ stderr = r"""sconsign: no entry `hello.obj' in `\.'
+sconsign: no entry `hello.obj' in `%(CC_dir)s'
+""" % locals())
test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj .sconsign",
- stdout = """\
+ stdout = r"""=== .:
+=== %(CC_dir)s:
=== sub1:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
=== sub2:
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub2_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals(),
+ stderr = r"""sconsign: no entry `hello.obj' in `\.'
+sconsign: no entry `hello.exe' in `\.'
+sconsign: no entry `hello.obj' in `\.'
+sconsign: no entry `hello.obj' in `%(CC_dir)s'
+sconsign: no entry `hello.exe' in `%(CC_dir)s'
+sconsign: no entry `hello.obj' in `%(CC_dir)s'
+""" % locals())
#test.run_sconsign(arguments = "-i -v .sconsign",
-# stdout = """\
-#=== sub1:
+# stdout = r"""=== sub1:
#hello.exe:
# implicit:
-# hello.obj: \S+
+# hello.obj: %(sig_re)s
#hello.obj:
# implicit:
-# hello.c: \S+
+# hello.c: %(sig_re)s
#=== sub2:
#hello.exe:
# implicit:
-# hello.obj: \S+
+# hello.obj: %(sig_re)s
#hello.obj:
# implicit:
-# hello.c: \S+
-# inc1.h: \S+
-# inc2.h: \S+
-#""")
+# hello.c: %(sig_re)s
+# inc1.h: %(sig_re)s
+# inc2.h: %(sig_re)s
+#inc1.h: %(sig_re)s
+#inc2.h: %(sig_re)s
+#""" % locals())
test.pass_test()
diff --git a/test/sconsign/script/Signatures.py b/test/sconsign/script/Signatures.py
index 9a3ce62..fc85133 100644
--- a/test/sconsign/script/Signatures.py
+++ b/test/sconsign/script/Signatures.py
@@ -35,6 +35,17 @@ import TestSConsign
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+CC = test.detect('CC', norm=1)
+LINK = test.detect('LINK', norm=1)
+if LINK is None: LINK = CC
+
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+sub1_hello_c = 'sub1/hello.c'
+sub1_hello_obj = 'sub1/hello.obj'
+
def re_sep(*args):
import os.path
import re
@@ -90,20 +101,29 @@ test.sleep()
test.run(arguments = '. --max-drift=1')
+sig_re = r'[0-9a-fA-F]{32}'
+date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
+
test.run_sconsign(arguments = "-e hello.exe -e hello.obj sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
+ stdout = r"""hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: None \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: None \d+ \d+
+ %(CC)s: None \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "-e hello.exe -e hello.obj -r sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.obj: \S+
-hello.obj: \S+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.c: \S+
-""")
+ stdout = r"""hello.exe: %(sig_re)s '%(date_re)s' \d+
+ %(sub1_hello_obj)s: %(sig_re)s '%(date_re)s' \d+
+ %(LINK)s: None '%(date_re)s' \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s '%(date_re)s' \d+
+ %(sub1_hello_c)s: None '%(date_re)s' \d+
+ %(CC)s: None '%(date_re)s' \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.pass_test()
diff --git a/test/sconsign/script/dblite.py b/test/sconsign/script/dblite.py
index fe49df6..1b359e2 100644
--- a/test/sconsign/script/dblite.py
+++ b/test/sconsign/script/dblite.py
@@ -33,8 +33,19 @@ import TestSConsign
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
+CC = test.detect('CC', norm=1)
+LINK = test.detect('LINK', norm=1)
+if LINK is None: LINK = CC
+
test.subdir('sub1', 'sub2')
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+sub1_hello_c = 'sub1/hello.c'
+sub1_hello_obj = 'sub1/hello.obj'
+
test.write('SConstruct', """
SConsignFile('my_sconsign')
SourceSignatures('timestamp')
@@ -83,21 +94,30 @@ test.sleep()
test.run(arguments = '. --max-drift=1')
-expect = """\
-=== sub1:
-hello.exe: \d+ None \d+ \d+
- hello.obj: \d+
-hello.obj: \d+ None \d+ \d+
- hello.c: \d+
-"""
-
-expect_r = """\
-=== sub1:
-hello.exe: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.obj: \d+
-hello.obj: \d+ None '\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' \d+
- hello.c: \d+
-"""
+sig_re = r'[0-9a-fA-F]{32}'
+date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
+
+expect = r"""=== sub1:
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: None \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: None \d+ \d+
+ %(CC)s: None \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals()
+
+expect_r = """=== sub1:
+hello.exe: %(sig_re)s '%(date_re)s' \d+
+ %(sub1_hello_obj)s: %(sig_re)s '%(date_re)s' \d+
+ %(LINK)s: None '%(date_re)s' \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s '%(date_re)s' \d+
+ %(sub1_hello_c)s: None '%(date_re)s' \d+
+ %(CC)s: None '%(date_re)s' \d+
+ %(sig_re)s \[.*\]
+""" % locals()
common_flags = '-e hello.exe -e hello.obj -d sub1'
diff --git a/test/sconsign/script/no-SConsignFile.py b/test/sconsign/script/no-SConsignFile.py
index b860770..1fcfbfd 100644
--- a/test/sconsign/script/no-SConsignFile.py
+++ b/test/sconsign/script/no-SConsignFile.py
@@ -33,13 +33,23 @@ import TestSConsign
test = TestSConsign.TestSConsign(match = TestSConsign.match_re)
-def re_sep(*args):
- import os.path
- import re
- return re.escape(apply(os.path.join, args))
+CC = test.detect('CC', norm=1)
+LINK = test.detect('LINK', norm=1)
+if LINK is None: LINK = CC
test.subdir('sub1', 'sub2')
+# Note: We don't use os.path.join() representations of the file names
+# in the expected output because paths in the .sconsign files are
+# canonicalized to use / as the separator.
+
+sub1_hello_c = 'sub1/hello.c'
+sub1_hello_obj = 'sub1/hello.obj'
+sub2_hello_c = 'sub2/hello.c'
+sub2_hello_obj = 'sub2/hello.obj'
+sub2_inc1_h = 'sub2/inc1.h'
+sub2_inc2_h = 'sub2/inc2.h'
+
test.write(['SConstruct'], """
SConsignFile(None)
env1 = Environment(PROGSUFFIX = '.exe', OBJSUFFIX = '.obj')
@@ -82,124 +92,160 @@ test.write(['sub2', 'inc2.h'], r"""\
#define STRING2 "inc2.h"
""")
-test.run(arguments = '--implicit-cache .')
+test.run(arguments = '--implicit-cache --tree=prune .')
-test.run_sconsign(arguments = "sub1/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
+sig_re = r'[0-9a-fA-F]{32}'
+
+expect = r"""hello.c: %(sig_re)s \d+ \d+
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals()
+
+test.run_sconsign(arguments = "sub1/.sconsign", stdout=expect)
+#test.run_sconsign(arguments = "sub1/.sconsign")
+#print test.stdout()
test.run_sconsign(arguments = "--raw sub1/.sconsign",
- stdout = """\
-hello.exe: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.obj: \S+
-hello.obj: {'bsig': '\S+', 'size': \d+L?, 'timestamp': \d+}
- hello.c: \S+
-""")
+ stdout = r"""hello.c: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+hello.exe: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub1_hello_obj)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(LINK)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+hello.obj: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sub1_hello_c)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(CC)s: {'csig': '%(sig_re)s', 'timestamp': \d+, 'size': \d+L?, '_version_id': 1}
+ %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "-v sub1/.sconsign",
- stdout = """\
+ stdout = r"""hello.c:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
hello.exe:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.obj: \S+
+ %(sub1_hello_obj)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(LINK)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
hello.obj:
- bsig: \S+
- csig: None
+ csig: %(sig_re)s
timestamp: \d+
size: \d+
implicit:
- hello.c: \S+
-""")
-
-test.run_sconsign(arguments = "-b -v sub1/.sconsign",
- stdout = """\
-hello.exe:
- bsig: \S+
-hello.obj:
- bsig: \S+
-""")
+ %(sub1_hello_c)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ %(CC)s:
+ csig: %(sig_re)s
+ timestamp: \d+
+ size: \d+
+ action: %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "-c -v sub1/.sconsign",
- stdout = """\
+ stdout = r"""hello.c:
+ csig: %(sig_re)s
hello.exe:
- csig: None
+ csig: %(sig_re)s
hello.obj:
- csig: None
-""")
+ csig: %(sig_re)s
+""" % locals())
test.run_sconsign(arguments = "-s -v sub1/.sconsign",
- stdout = """\
+ stdout = r"""hello.c:
+ size: \d+
hello.exe:
size: \d+
hello.obj:
size: \d+
-""")
+""" % locals())
test.run_sconsign(arguments = "-t -v sub1/.sconsign",
- stdout = """\
+ stdout = r"""hello.c:
+ timestamp: \d+
hello.exe:
timestamp: \d+
hello.obj:
timestamp: \d+
-""")
+""" % locals())
test.run_sconsign(arguments = "-e hello.obj sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
+ stdout = r"""hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "-e hello.obj -e hello.exe -e hello.obj sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
-
-# XXX NOT SURE IF THIS IS RIGHT!
-sub2_inc1_h = re_sep('sub2', 'inc1.h')
-sub2_inc2_h = re_sep('sub2', 'inc2.h')
+ stdout = r"""hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.run_sconsign(arguments = "sub2/.sconsign",
- stdout = """\
-hello.exe: \S+ None \d+ \d+
- hello.obj: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-""")
+ stdout = r"""hello.c: %(sig_re)s \d+ \d+
+hello.exe: %(sig_re)s \d+ \d+
+ %(sub2_hello_obj)s: %(sig_re)s \d+ \d+
+ %(LINK)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+inc1.h: %(sig_re)s \d+ \d+
+inc2.h: %(sig_re)s \d+ \d+
+""" % locals())
#test.run_sconsign(arguments = "-i -v sub2/.sconsign",
-# stdout = """\
-#hello.exe:
+# stdout = r"""hello.c: %(sig_re)s \d+ \d+
+#hello.exe: %(sig_re)s \d+ \d+
# implicit:
-# hello.obj: \S+ None \d+ \d+
-#hello.obj:
+# hello.obj: %(sig_re)s \d+ \d+
+#hello.obj: %(sig_re)s \d+ \d+
# implicit:
-# hello.c: None \S+ \d+ \d+
-# inc1.h: None \S+ \d+ \d+
-# inc2.h: None \S+ \d+ \d+
-#""")
+# hello.c: %(sig_re)s \d+ \d+
+# inc1.h: %(sig_re)s \d+ \d+
+# inc2.h: %(sig_re)s \d+ \d+
+#""" % locals())
test.run_sconsign(arguments = "-e hello.obj sub2/.sconsign sub1/.sconsign",
- stdout = """\
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
- inc1.h: \S+
- inc2.h: \S+
-hello.obj: \S+ None \d+ \d+
- hello.c: \S+
-""")
+ stdout = r"""hello.obj: %(sig_re)s \d+ \d+
+ %(sub2_hello_c)s: %(sig_re)s \d+ \d+
+ %(sub2_inc1_h)s: %(sig_re)s \d+ \d+
+ %(sub2_inc2_h)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+hello.obj: %(sig_re)s \d+ \d+
+ %(sub1_hello_c)s: %(sig_re)s \d+ \d+
+ %(CC)s: %(sig_re)s \d+ \d+
+ %(sig_re)s \[.*\]
+""" % locals())
test.pass_test()
diff --git a/test/timestamp-fallback.py b/test/timestamp-fallback.py
index 7576023..9d89d70 100644
--- a/test/timestamp-fallback.py
+++ b/test/timestamp-fallback.py
@@ -24,6 +24,11 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""
+Verify falling back to 'timestamp' behavior if there is no native
+hashlib and no underlying md5 module available.
+"""
+
import imp
import os
import os.path
@@ -33,6 +38,15 @@ import TestSCons
test = TestSCons.TestSCons()
try:
+ file, name, desc = imp.find_module('hashlib')
+except ImportError:
+ pass
+else:
+ msg = "This version of Python has a 'hashlib' module.\n" + \
+ "Skipping test of falling back to timestamps.\n"
+ test.skip_test(msg)
+
+try:
file, name, desc = imp.find_module('md5')
except ImportError:
pass
diff --git a/test/up-to-date.py b/test/up-to-date.py
index cec5952..366d017 100644
--- a/test/up-to-date.py
+++ b/test/up-to-date.py
@@ -24,9 +24,12 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
+"""
+Verify appropriate printing of "is up to date" messages.
+"""
+
import string
-import sys
+
import TestSCons
_python_ = TestSCons._python_
@@ -66,5 +69,29 @@ scons: `f3.out' is up to date.
test.run(arguments = 'f1.out f2.out f3.out f4.out', stdout = expect)
-test.pass_test()
+# Make sure all of the "up to date" messages get printed even when -j
+# is used. This broke during signature refactoring development.
+expected_lines = [
+ "scons: `f1.out' is up to date.",
+ "scons: `f2.out' is up to date.",
+ "scons: `f3.out' is up to date.",
+ "scons: `f4.out' is up to date.",
+]
+test.run(options = '-j4 f1.out f2.out f3.out f4.out')
+stdout = test.stdout()
+
+missing = []
+for line in expected_lines:
+ if string.find(stdout, line) == -1:
+ missing.append(line)
+
+if missing:
+ print "Missing the following expected lines:"
+ for line in missing:
+ print line
+ print "STDOUT =========="
+ print stdout
+ test.fail_test()
+
+test.pass_test()