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