1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* lib/rake: updated to rake code to rake-0.8.7 source code base.

* lib/rake/loaders/makefile.rb (Rake::MakefileLoader#process_line):
  respace dependencies too.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25199 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2009-10-02 19:07:55 +00:00
parent a0f667c33e
commit 719b0f8e30
71 changed files with 6679 additions and 72 deletions

View file

@ -1,3 +1,10 @@
Sat Oct 3 04:07:52 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/rake: updated to rake code to rake-0.8.7 source code base.
* lib/rake/loaders/makefile.rb (Rake::MakefileLoader#process_line):
respace dependencies too.
Sat Oct 3 02:59:21 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (assignable_gen): get rid of macro collision.

440
doc/rake/CHANGES Normal file
View file

@ -0,0 +1,440 @@
= Rake Changelog
== Version 0.8.7
* Fixed EXEEXT for JRuby on windows.
== Version 0.8.6
* Minor fixes to the RDoc generation (removed dependency on darkfish
and removed inline source option).
== Version 0.8.5
* Better support for the system command on Windows.
== Version 0.8.4
* Preserve case when locating rakefiles (patch from James
M. Lawrence/quix)
* Better support for windows paths in the test task (patch from Simon
Chiang/bahuvrihi)
* Windows system dir search order is now: HOME, HOMEDRIVE + HOMEPATH,
APPDATA, USERPROFILE (patch from Luis Lavena)
* MingGW is now recognized as a windows platform. (patch from Luis
Lavena)
* Numerous fixes to the windows test suite (patch from Luis Lavena).
* Improved Rakefile case insensitivity testing (patch from Luis
Lavena).
* Fixed stray ARGV option problem that was interfering with
Test::Unit::Runner.
* Fixed default verbose mode (was accidently changed to false).
* Removed reference to manage_gem to fix the warning produced by the
gem package task.
== Version 0.8.3
* Enhanced the system directory detection in windows. We now check
HOMEDRIVE/HOMEPATH and USERPROFILE if APPDATA isn't found. (Patch
supplied by James Tucker). Rake no long aborts if it can't find the
directory.
* Added fix to handle ruby installations in directories with spaces in
their name.
== Version 0.8.2
* Fixed bug in package task so that it will include the subdir
directory in the package for testing. (Bug found by Adam Majer)
* Added ENV var to rakefile to prevent OS X from including extended
attribute junk in a tar file. (Bug found by Adam Majer)
* Fixed filename dependency order bug in test_inspect_pending and
test_to_s_pending. (Bug found by Adam Majer)
* Fixed check for file utils options to make them immune to the
symbol/string differences. (Patch supplied by Edwin Pratomo)
* Fixed bug with rules involving multiple source (Patch supplied by
Emanuel Indermühle)
* Switched from getoptlong to optparse (patches supplied by Edwin
Pratomo)
* The -T option will now attempt to dynamically sense the size of the
terminal. RAKE_COLUMNS will override any dynamic sensing.
* FileList#clone and FileList#dup have better sematics w.r.t. taint
and freeze.
* Added ability clear prerequisites, and/or actions from an existing
task.
* Added the ability to reenable a task to be invoked a second time.
* Changed RDoc test task to have no default template. This makes it
easier for the tempate to pick up the template from the environment.
* Changed from using Mutex to Monitor. Evidently Mutex causes thread
join errors when Ruby is compiled with -disable-pthreads. (Patch
supplied by Ittay Dror)
* Fixed bug in makefile parser that had problems with extra spaces in
file task names. (Patch supplied by Ittay Dror)
* Added a performance patch for reading large makefile dependency
files. (Patch supplied by Ittay Dror)
* Default values for task arguments can easily be specified with the
:with_defaults method. (Idea for default argument merging supplied
by (Adam Q. Salter)
* The -T output will only self-truncate if the output is a tty.
However, if RAKE_COLUMNS is explicitly set, it will be honored in
any case. (Patch provided by Gavin Stark).
* Numerous fixes for running under windows. A big thanks to Bheeshmar
Redheendran for spending a good part of the afternoon at the
Lonestar Ruby Conference to help me work out these issues.
== Version 0.8.1
* Removed requires on parsedate.rb (in Ftptools)
* Removed ftools from rake.rb. Made it options in sys.rb
== Version 0.8.0
* Added task parameters (e.g. "rake build[version7]")
* Made task parameters passable to prerequisites.
* Comments are limited to 80 columns or so (suggested by Jamis Buck).
* Added -D to display full comments (suggested by Jamis Buck).
* The rake program will set the status value used in any explicit
exit(n) calls. (patch provided by Stephen Touset)
* Fixed error in functional tests that were not including session (and
silently skipping the functionl tests.
* Removed --usage and make -h the same as -H.
* Make a prettier inspect for tasks.
== Version 0.7.3
* Added existing and existing! methods to FileList
* FileLists now claim to be Arrays (via is_a?) to get better support
from the FileUtil module.
* Added init and top_level for custom rake applications.
== Version 0.7.2
* Error messages are now send to stderr rather than stdout (from
Payton Quackenbush).
* Better error handling on invalid command line arguments (from Payton
Quackenbush).
* Added rcov task and updated unit testing for better code coverage.
* Fixed some bugs where the application object was going to the global
appliation instead of using its own data.
* Added square and curly bracket patterns to FileList#include (Tilman
Sauerbeck).
* Added plain filename support to rule dependents (suggested by Nobu
Nakada).
* Added pathmap support to rule dependents.
* Added a 'tasks' method to a namespace to get a list of tasks
associated with the namespace.
* Fixed the method name leak from FileUtils (bug found by Glenn
Vanderburg).
* Added rake_extension to handle detection of extension collisions.
* Added test for noop, bad_option and verbose flags to sh command.
* Removed dependency on internal fu_xxx functions from FileUtils.
* Added a 'shame' task to the Rakefile.
* Added tar_command and zip_command options to the Package task.
* Added a description to the gem task in GemPackageTask.
* Fixed a bug when rules have multiple prerequisites (patch by Joel
VanderWerf)
* Added a protected 'require "rubygems"' to test/test_application to
unbreak cruisecontrol.rb.
* Added the handful of RakeFileUtils to the private method as well.
* Added block based exclusion.
* The clean task will no longer delete 'core' if it is a directory.
* Removed rake_dup. Now we just simply rescue a bad dup.
* Refactored the FileList reject logic to remove duplication.
* Removed if __FILE__ at the end of the rake.rb file.
== Version 0.7.1
* Added optional filter parameter to the --tasks command line option.
* Added flatten to allow rule transform procs to return lists of
prereqs (Joel VanderWerf provided patch).
* Added pathmap to String and FileList.
* The -r option will now load .rake files (but a straight require
doesn't yet). NOTE: This is experimental ... it may be
discontinued.
* The -f option without a value will disable the search for a
Rakefile. The assumption is that the -r files are adequate.
* Fixed the safe_ln function to fall back to cp in more error
scenarios.
== Version 0.7.0
* Added Rake.original_dir to return the original starting directory of
the rake application.
* Added safe_ln support for openAFS (from Ludvig Omholt).
* Added --trace reminder on short exception messages (David Heinemeier
Hansson suggestion).
* Added multitask declaration that executes prerequisites in
parallel. (Doug Young providied an initial implementation).
* Fixed missing_const hack to be compatible with Rails. (Jamis Buck
supplied test case).
* Made the RDoc task default to internal (in-process) RDoc formatting.
The old behavior is still available by setting the +external+ flag
to true.
* Rakefiles are now loaded with the expanded path to prevent
accidental polution from the Ruby load path.
* The +namespace+ command now returns a NameSpace object that can be
used to lookup tasks defined in that namespace. This allows for
better anonymous namespace behavior.
* Task objects my now be used in prerequisite lists directly.
== Version 0.6.1
* Rebuilt 0.6.0 gem without signing.
== Version 0.6.0
* Fixed file creation bug in the unit tests (caused infinite loop on
windows).
* Fixed bug where session based functional tests were run under
windows.
* Fixed bug in directory tasks so that updating a directory will not
retrigger file tasks depending on the directory (see
FileCreationTask and EarlyTime).
* Added egrep to FileList
* ruby command now runs same ruby version as rake.
* Added investigation to task object. (suggested by Martin Fowler)
* Added ruby_opts to the test task to allow arbitrary ruby options to
be passed to the test script. (Greg Fast)
* Fixed the test loader to ignore options. (Greg Fast)
* Moved Task, FileTask, FileCreationTask and RakeApp into the Rake
module namespace. Old style namespace behavior can be invoked via
the --classic-namespace option. (requested by Kelly Felkins).
* GemTask is now sensitive to the gem platform (Masao Mutoh).
* A non-existing file prerequisite will no longer cause an exception
(Philipp Neubeck).
* Multiple prerequisites on Rake rules now allowed (initial patch
supplied by Stuart Jansen).
== Version 0.5.4
* Added double quotes to the test runner.
* Added .svn to default ignore list.
* Updated FileList#include to support nested arrays and filelists.
== Version 0.5.3
* Added support for importing Rakefile and other dependencies.
* Fixed bug so that now rules can chain off of existing tasks as well
as existing files.
* Fixed verbose flag bug in the testing task. Shortened some failure
messages.
* Make FileUtils methods private at the top level module to avoid
accidental method leaking into other objects.
* Added test loader option to test task. "testrb" is no longer the
default test loader. It is now eating syntax errors that should
halt the unit tests.
* Revamped FileList so that it works more like and array (addressed
flatten bug). Added many tests around file list.
* Added +ext+ method to both String and FileList.
== Version 0.5.0
* Fixed documentation that was lacking the Rake module name (Tilman
Sauerbeck).
* Added tar.gz and tar.bz2 support to package task (Tilman Sauerbeck).
* Recursive rules are now supported (Tilman Sauerbeck).
* Added warning option for the Test Task (requested by Eric Hodel).
* The jamis rdoc template is only used if it exists.
* Added fix for Ruby 1.8.2 test/unit and rails problem.
* Added contributed rake man file (Jani Monoses).
* Added Brian Candler's fix for problems in --trace and --dry-run
mode.
== Version 0.4.15
* Fixed a bug that prevented the TESTOPTS flag from working with the
revised for 1.8.2 test task.
* Updated the docs on --trace to indicate that it also enables a full
backtrace on errors.
== Version 0.4.14
* Modified the TestTask to workaround the Ruby 1.8.2 change in
autoexecuting unit tests.
== Version 0.4.13
* Fixed the dry-run flag so it is operating again.
* Multiple arguments to sh and ruby commands will not be interpreted
by the shell (patch provided by Jonathan Paisley).
== Version 0.4.12
* Added --silent (-s) to suppress the (in directory) rake message.
== Version 0.4.11
* Changed the "don't know how to rake" message (finally)
* Changes references to a literal "Rakefile" to reference the global
variable $rakefile (which contains the actual name of the rakefile).
== Version 0.4.10
* Added block support to the "sh" command, allowing users to take
special actions on the result of the system call. E.g.
sh "shell_command" do |ok, res|
puts "Program returned #{res.exitstatus}" if ! ok
end
== Version 0.4.9
* Switched to Jamis Buck's RDoc template.
* Removed autorequire from Rake's gem spec. This prevents the Rake
libraries from loading while using rails.
== Version 0.4.8
* Added support for .rb versions of Rakefile.
* Removed \\\n's from test task.
* Fixed Ruby 1.9 compatibility issue with FileList.
== Version 0.4.7
* Fixed problem in FileList that caused Ruby 1.9 to go into infinite
recursion. Since to_a was removed from Object, it does not need to
added back into the list of methods to rewrite in FileList. (Thanks
to Kent Sibilev for pointing this out).
== Version 0.4.6
* Removed test version of ln in FileUtils that prevented safe_ln from
using ln.
== Version 0.4.5
* Upgraded comments in TestTask.
* FileList to_s and inspect now automatically resolve pending changes.
* FileList#exclude properly returns the FileList.
== Version 0.4.4
* Fixed initialization problem with @comment.
* Now using multi -r technique in TestTask. Switch Rakefile back to
using the built-in test task macros because the rake runtime is no
longer needed.
* Added 'TEST=filename' and 'TESTOPTS=options' to the Test Task
macros.
* Allow a +test_files+ attribute in test tasks. This allows more
flexibility in specifying test files.
== Version 0.4.3
* Fixed Comment leakage.
== Version 0.4.2
* Added safe_ln that falls back to a copy if a file link is not supported.
* Package builder now uses safe_ln.
== Version 0.4.1
* Task comments are now additive, combined with "/".
* Works with (soon to be released) rubygems 0.6.2 (or 0.7.0)
== Version 0.4.0
* FileList now uses deferred loading. The file system is not searched
until the first call that needs the file names.
* VAR=VALUE options are now accepted on the command line and are
treated like environment variables. The values may be tested in a
Rakefile by referencing ENV['VAR'].
* File.mtime is now used (instead of File.new().mtime).
== Version 0.3.2.x
* Removed some hidden dependencies on rubygems. Tests now will test
gems only if they are installed.
* Removed Sys from some example files. I believe that is that last
reference to Sys outside of the contrib area.
* Updated all copyright notices to include 2004.
== Version 0.3.2
* GEM Installation now works with the application stub.
== Version 0.3.1
* FileLists now automatically ignore CVS, .bak, !
* GEM Installation now works.
== Version 0.3.0
Promoted 0.2.10.
== Version 0.2.10
General
* Added title to Rake's rdocs
* Contrib packages are no longer included in the documentation.
RDoc Issues
* Removed default for the '--main' option
* Fixed rendering of the rdoc options
* Fixed clean/clobber confusion with rerdoc
* 'title' attribute added
Package Task Library Issues
* Version (or explicit :noversion) is required.
* +package_file+ attribute is now writable
FileList Issues
* Dropped bang version of exclude. Now using ant-like include/exclude semantics.
* Enabled the "yield self" idiom in FileList#initialize.
== Version 0.2.9
This version contains numerous changes as the RubyConf.new(2003)
presentation was being prepared. The changes include:
* The monolithic rubyapp task library is in the process of being
dropped in favor of lighter weight task libraries.
== Version 0.2.7
* Added "desc" for task descriptions.
* -T will now display tasks with descriptions.
* -P will display tasks and prerequisites.
* Dropped the Sys module in favor of the 1.8.x FileUtils module. Sys
is still supported in the contrib area.
== Version 0.2.6
* Moved to RubyForge
== Version 0.2.5
* Switched to standard ruby app builder.
* Added no_match option to file matcher.
== Version 0.2.4
* Fixed indir, which neglected to actually change directories.
== Version 0.2.3
* Added rake module for a help target
* Added 'for_files' to Sys
* Added a $rakefile constant
* Added test for selecting proper rule with multiple targets.

196
doc/rake/README Normal file
View file

@ -0,0 +1,196 @@
= RAKE -- Ruby Make
Supporting Rake version: 0.8.6
This package contains Rake, a simple ruby build program with
capabilities similar to make.
Rake has the following features:
* Rakefiles (rake's version of Makefiles) are completely defined in
standard Ruby syntax. No XML files to edit. No quirky Makefile
syntax to worry about (is that a tab or a space?)
* Users can specify tasks with prerequisites.
* Rake supports rule patterns to synthesize implicit tasks.
* Flexible FileLists that act like arrays but know about manipulating
file names and paths.
* A library of prepackaged tasks to make building rakefiles easier. For example,
tasks for building tarballs, gems and RDoc output are provided.
* Supports parallel execution of tasks.
== Installation
=== Gem Installation
Download and install rake with the following.
gem install rake
=== Normal Installation
You can download the source tarball of the latest version of Rake from
* http://rubyforge.org/project/showfiles.php?group_id=50
Extract the tarball and run
% ruby install.rb
from its distribution directory.
== Usage
=== Simple Example
First, you must write a "Rakefile" file which contains the build rules. Here's
a simple example:
task :default => [:test]
task :test do
ruby "test/unittest.rb"
end
This Rakefile has two tasks:
* A task named "test", which - upon invocation - will run a unit test file in
Ruby.
* A task named "default". This task does nothing by itself, but it has exactly
one dependency, namely the "test" task. Invoking the "default" task will
cause Rake to invoke the "test" task as well.
Running the "rake" command without any options will cause it to run the
"default" task in the Rakefile:
% ls
Rakefile test/
% rake
(in /home/some_user/Projects/rake)
ruby test/unittest.rb
....unit test output here...
Type "rake --help" for all available options.
=== More Information
* For details on Rake's command-line invocation, read
doc/command_line_usage.rdoc[http://rake.rubyforge.org/files/doc/command_line_usage_rdoc.html]
* For details on writing Rakefiles, see
doc/rakefile.rdoc[http://rake.rubyforge.org/files/doc/rakefile_rdoc.html].
* For the original announcement of Rake, see
doc/rational.rdoc[http://rake.rubyforge.org/files/doc/rational_rdoc.html].
* For a glossary of terms, see
doc/glossary.rdoc[http://rake.rubyforge.org/files/doc/glossary_rdoc.html].
== Development
=== Source Repository
Rake is currently hosted at github. The github web page is
http://github.com/jimweirich/rake. The public git clone URL is
* git://github.com/jimweirich/rake.git
=== Running the Rake Test Suite
If you wish to run the unit and functional tests that come with Rake:
* Install the 'session' gem in order to run the functional tests.
* CD into the top project directory of rake.
* Type one of the following:
rake # If you have a version of rake installed
ruby -Ilib bin/rake # If you do not have a version of rake installed.
=== Issues and Bug Reports
Bugs, features requests and other issues can be logged at
* http://onestepback.org/redmine/projects/show/rake
You will need an account to before you can post issues. Register at
http://onestepback.org/redmine/account/register. Or you can send me
an email (at jim dot weirich at gmail dot com)
== Online Resources
=== Rake References
* Rake Documentation Home: http://docs.rubyrake.org
* Rake Project Page: http://rubyforge.org/projects/rake
* Rake API Documents: http://rake.rubyforge.org
* Rake Source Code Repo: http://github.com/jimweirich/rake
* Rake Git Repo Clone URL: git://github.com/jimweirich/rake.git
=== Presentations and Articles about Rake
* Jim Weirich's 2003 RubyConf presentation: http://onestepback.org/articles/buildingwithrake/
* Martin Fowler's article on Rake: http://martinfowler.com/articles/rake.html
== Other Make Reinvisionings ...
Rake is a late entry in the make replacement field. Here are links to
other projects with similar (and not so similar) goals.
* http://directory.fsf.org/bras.html -- Bras, one of earliest
implementations of "make in a scripting language".
* http://www.a-a-p.org -- Make in Python
* http://www.aromatic.com/tools/jam.txt -- JAM, Java Automated Make
* http://ant.apache.org -- The Ant project
* http://ppt.perl.org/commands/make/index.html -- Make from the Perl
Power Tools implementation.
* http://search.cpan.org/search?query=PerlBuildSystem -- The Perl Build System
* http://make.rubyforge.org -- Rant, another Ruby make tool.
== Credits
[<b>Ryan Dlugosz</b>] For the initial conversation that sparked Rake.
[<b>nobu.nokada@softhome.net</b>] For the initial patch for rule support.
[<b>Tilman Sauerbeck <tilman@code-monkey.de></b>] For the recursive rule patch.
== License
Rake is available under an MIT-style license.
:include: MIT-LICENSE
== Support
The Rake homepage is http://rake.rubyforge.org. You can find the Rake
RubyForge page at http://rubyforge.org/projects/rake.
Feel free to submit commits or feature requests. If you send a patch,
remember to update the corresponding unit tests. If fact, I prefer
new feature to be submitted in the form of new unit tests.
For other information, feel free to ask on the ruby-talk mailing list
(which is mirrored to comp.lang.ruby) or contact
jim dot weirich at gmail.com.
---
= Other stuff
Author:: Jim Weirich <jim.weirich@gmail.com>
Requires:: Ruby 1.8.0 or later
License:: Copyright 2003-2008 by Jim Weirich.
Released under an MIT-style license. See the LICENSE file
included in the distribution.
== Warranty
This software is provided "as is" and without any express or
implied warranties, including, without limitation, the implied
warranties of merchantibility and fitness for a particular
purpose.

View file

@ -0,0 +1,102 @@
= Rake Command Line Usage
Rake is invoked from the command line using:
% rake [<em>options</em> ...] [<em>VAR</em>=<em>VALUE</em>] [<em>targets</em> ...]
Options are:
[<tt><em>name</em>=<em>value</em></tt>]
Set the environment variable <em>name</em> to <em>value</em>
during the execution of the <b>rake</b> command. You can access
the value by using ENV['<em>name</em>'].
[<tt>--classic-namespace</tt> (-n)]
Import the Task, FileTask, and FileCreateTask into the top-level
scope to be compatible with older versions of Rake. Alternatively
you can include the line <code>require
'rake/classic_namespace'</code> in your Rakefile to get the
classic behavior.
[<tt>--describe</tt> _pattern_ (-D)]
Describe the tasks (matching optional PATTERN), then exit.
[<tt>--dry-run</tt> (-n)]
Do a dry run. Print the tasks invoked and executed, but do not
actually execute any of the actions.
[<tt>--execute</tt> _code_ (-e)]
Execute some Ruby code and exit.
[<tt>--execute-print</tt> _code_ (-p)]
Execute some Ruby code, print the result, and exit.
[<tt>--execute-continue</tt> _code_ (-p)]
Execute some Ruby code, then continue with normal task processing.
[<tt>--help</tt> (-H)]
Display some help text and exit.
[<tt>--libdir</tt> _directory_ (-I)]
Add _directory_ to the list of directories searched for require.
[<tt>--nosearch</tt> (-N)]
Do not search for a Rakefile in parent directories.
[<tt>--prereqs</tt> (-P)]
Display a list of all tasks and their immediate prerequisites.
[<tt>--quiet</tt> (-q)]
Do not echo commands from FileUtils.
[<tt>--rakefile</tt> _filename_ (-f)]
Use _filename_ as the name of the rakefile. The default rakefile
names are +rakefile+ and +Rakefile+ (with +rakefile+ taking
precedence). If the rakefile is not found in the current
directory, +rake+ will search parent directories for a match. The
directory where the Rakefile is found will become the current
directory for the actions executed in the Rakefile.
[<tt>--rakelibdir</tt> _rakelibdir_ (-R)]
Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')
[<tt>--require</tt> _name_ (-r)]
Require _name_ before executing the Rakefile.
[<tt>--rules</tt>]
Trace the rules resolution.
[<tt>--silent (-s)</tt>]
Like --quiet, but also suppresses the 'in directory' announcement.
[<tt>--system</tt> (-g)]
Use the system wide (global) rakefiles. The project Rakefile is
ignored. By default, the system wide rakefiles are used only if no
project Rakefile is found. On Unix-like system, the system wide
rake files are located in $HOME/.rake. On a windows system they
are stored in $APPDATA/Rake.
[<tt>--no-system</tt> (-G)]
Use the project level Rakefile, ignoring the system-wide (global)
rakefiles.
[<tt>--tasks</tt> (-T)]
Display a list of the major tasks and their comments. Comments
are defined using the "desc" command.
[<tt>--trace</tt> (-t)]
Turn on invoke/execute tracing. Also enable full backtrace on
errors.
[<tt>--usage</tt> (-h)]
Display a usage message and exit.
[<tt>--verbose</tt> (-v)]
Echo the Sys commands to standard output.
[<tt>--version</tt> (-V)]
Display the program version and exit.
In addition, any command line option of the form
<em>VAR</em>=<em>VALUE</em> will be added to the environment hash
<tt>ENV</tt> and may be tested in the Rakefile.

View file

@ -0,0 +1,38 @@
# Example Rakefile -*- ruby -*-
task :default => [:main]
file "a.o" => ["a.c"] do |t|
src = t.name.sub(/\.o$/, '.c')
sh "gcc #{src} -c -o #{t.name}"
end
file "b.o" => ["b.c"] do |t|
src = t.name.sub(/\.o$/, '.c')
sh "gcc #{src} -c -o #{t.name}"
end
file "main.o" => ["main.c"] do |t|
src = t.name.sub(/\.o$/, '.c')
sh "gcc #{src} -c -o #{t.name}"
end
OBJFILES = ["a.o", "b.o", "main.o"]
task :obj => OBJFILES
file "main" => OBJFILES do |t|
sh "gcc -o #{t.name} main.o a.o b.o"
end
task :clean do
rm_f FileList['*.o']
Dir['*~'].each { |fn| rm_f fn }
end
task :clobber => [:clean] do
rm_f "main"
end
task :run => ["main"] do
sh "./main"
end

View file

@ -0,0 +1,35 @@
# Example Rakefile -*- ruby -*-
# Using the power of Ruby
task :default => [:main]
def ext(fn, newext)
fn.sub(/\.[^.]+$/, newext)
end
SRCFILES = Dir['*.c']
OBJFILES = SRCFILES.collect { |fn| ext(fn,".o") }
OBJFILES.each do |objfile|
srcfile = ext(objfile, ".c")
file objfile => [srcfile] do |t|
sh "gcc #{srcfile} -c -o #{t.name}"
end
end
file "main" => OBJFILES do |t|
sh "gcc -o #{t.name} main.o a.o b.o"
end
task :clean do
rm_f FileList['*.o']
Dir['*~'].each { |fn| rm_f fn }
end
task :clobber => [:clean] do
rm_f "main"
end
task :run => ["main"] do
sh "./main"
end

6
doc/rake/example/a.c Normal file
View file

@ -0,0 +1,6 @@
#include <stdio.h>
void a()
{
printf ("In function a\n");
}

6
doc/rake/example/b.c Normal file
View file

@ -0,0 +1,6 @@
#include <stdio.h>
void b()
{
printf ("In function b\n");
}

11
doc/rake/example/main.c Normal file
View file

@ -0,0 +1,11 @@
#include <stdio.h>
extern void a();
extern void b();
int main ()
{
a();
b();
return 0;
}

51
doc/rake/glossary.rdoc Normal file
View file

@ -0,0 +1,51 @@
= Glossary
[<b>action</b>]
Code to be executed in order to perform a task. Actions in a
rakefile are specified in a code block (usually delimited by
+do+/+end+ pairs.
[<b>execute</b>]
When a task is executed, all of its actions are performed, in
the order they were defined. Note that unlike
<tt>invoke</tt>, <tt>execute</tt> always executes the actions
(without invoking or executing the prerequisites).
[<b>file task</b> (FileTask)]
A file task is a task whose purpose is to create a file
(which has the same name as the task). When invoked, a file
task will only execute if one or more of the following
conditions are true.
1. The associated file does not exist.
2. A prerequisite has a later time stamp than the existing file.
Because normal Tasks always have the current time as
timestamp, a FileTask that has a normal Task prerequisite
will always execute.
[<b>invoke</b>]
When a task is invoked, first we check to see if it has been
invoked before. if it has been, then nothing else is done.
If this is the first time its been invoked, then we invoke
each of its prerequisites. Finally, we check to see if we
need to execute the actions of this task by calling
<tt>needed?</tt>. Finally, if the task is needed, we execute
its actions.
NOTE: Currently prerequisites are invoked even if the task is
not needed. This may change in the future.
[<b>prerequisites</b>]
Every task has a set (possiblity empty) of prerequisites. A
prerequisite P to Task T is itself a task that must be invoked
before Task T.
[<b>rule</b>]
A rule is a recipe for synthesizing a task when no task is
explicitly defined. Rules generally synthesize file tasks.
[<b>task</b> (Task)]
Basic unit of work in a rakefile. A task has a name, a set of
prerequisites and a list of actions to be performed.

591
doc/rake/jamis.rb Normal file
View file

@ -0,0 +1,591 @@
module RDoc
module Page
FONTS = "\"Bitstream Vera Sans\", Verdana, Arial, Helvetica, sans-serif"
STYLE = <<CSS
a {
color: #00F;
text-decoration: none;
}
a:hover {
color: #77F;
text-decoration: underline;
}
body, td, p {
font-family: %fonts%;
background: #FFF;
color: #000;
margin: 0px;
font-size: small;
}
#content {
margin: 2em;
}
#description p {
margin-bottom: 0.5em;
}
.sectiontitle {
margin-top: 1em;
margin-bottom: 1em;
padding: 0.5em;
padding-left: 2em;
background: #005;
color: #FFF;
font-weight: bold;
border: 1px dotted black;
}
.attr-rw {
padding-left: 1em;
padding-right: 1em;
text-align: center;
color: #055;
}
.attr-name {
font-weight: bold;
}
.attr-desc {
}
.attr-value {
font-family: monospace;
}
.file-title-prefix {
font-size: large;
}
.file-title {
font-size: large;
font-weight: bold;
background: #005;
color: #FFF;
}
.banner {
background: #005;
color: #FFF;
border: 1px solid black;
padding: 1em;
}
.banner td {
background: transparent;
color: #FFF;
}
h1 a, h2 a, .sectiontitle a, .banner a {
color: #FF0;
}
h1 a:hover, h2 a:hover, .sectiontitle a:hover, .banner a:hover {
color: #FF7;
}
.dyn-source {
display: none;
background: #FFE;
color: #000;
border: 1px dotted black;
margin: 0.5em 2em 0.5em 2em;
padding: 0.5em;
}
.dyn-source .cmt {
color: #00F;
font-style: italic;
}
.dyn-source .kw {
color: #070;
font-weight: bold;
}
.method {
margin-left: 1em;
margin-right: 1em;
margin-bottom: 1em;
}
.description pre {
padding: 0.5em;
border: 1px dotted black;
background: #FFE;
}
.method .title {
font-family: monospace;
font-size: large;
border-bottom: 1px dashed black;
margin-bottom: 0.3em;
padding-bottom: 0.1em;
}
.method .description, .method .sourcecode {
margin-left: 1em;
}
.description p, .sourcecode p {
margin-bottom: 0.5em;
}
.method .sourcecode p.source-link {
text-indent: 0em;
margin-top: 0.5em;
}
.method .aka {
margin-top: 0.3em;
margin-left: 1em;
font-style: italic;
text-indent: 2em;
}
h1 {
padding: 1em;
border: 1px solid black;
font-size: x-large;
font-weight: bold;
color: #FFF;
background: #007;
}
h2 {
padding: 0.5em 1em 0.5em 1em;
border: 1px solid black;
font-size: large;
font-weight: bold;
color: #FFF;
background: #009;
}
h3, h4, h5, h6 {
padding: 0.2em 1em 0.2em 1em;
border: 1px dashed black;
color: #000;
background: #AAF;
}
.sourcecode > pre {
padding: 0.5em;
border: 1px dotted black;
background: #FFE;
}
CSS
XHTML_PREAMBLE = %{<?xml version="1.0" encoding="%charset%"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
}
HEADER = XHTML_PREAMBLE + <<ENDHEADER
<html>
<head>
<title>%title%</title>
<meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
<link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
<script language="JavaScript" type="text/javascript">
// <![CDATA[
function toggleSource( id )
{
var elem
var link
if( document.getElementById )
{
elem = document.getElementById( id )
link = document.getElementById( "l_" + id )
}
else if ( document.all )
{
elem = eval( "document.all." + id )
link = eval( "document.all.l_" + id )
}
else
return false;
if( elem.style.display == "block" )
{
elem.style.display = "none"
link.innerHTML = "show source"
}
else
{
elem.style.display = "block"
link.innerHTML = "hide source"
}
}
function openCode( url )
{
window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
}
// ]]>
</script>
</head>
<body>
ENDHEADER
FILE_PAGE = <<HTML
<table border='0' cellpadding='0' cellspacing='0' width="100%" class='banner'>
<tr><td>
<table width="100%" border='0' cellpadding='0' cellspacing='0'><tr>
<td class="file-title" colspan="2"><span class="file-title-prefix">File</span><br />%short_name%</td>
<td align="right">
<table border='0' cellspacing="0" cellpadding="2">
<tr>
<td>Path:</td>
<td>%full_path%
IF:cvsurl
&nbsp;(<a href="%cvsurl%">CVS</a>)
ENDIF:cvsurl
</td>
</tr>
<tr>
<td>Modified:</td>
<td>%dtm_modified%</td>
</tr>
</table>
</td></tr>
</table>
</td></tr>
</table><br>
HTML
###################################################################
CLASS_PAGE = <<HTML
<table width="100%" border='0' cellpadding='0' cellspacing='0' class='banner'><tr>
<td class="file-title"><span class="file-title-prefix">%classmod%</span><br />%full_name%</td>
<td align="right">
<table cellspacing=0 cellpadding=2>
<tr valign="top">
<td>In:</td>
<td>
START:infiles
HREF:full_path_url:full_path:
IF:cvsurl
&nbsp;(<a href="%cvsurl%">CVS</a>)
ENDIF:cvsurl
END:infiles
</td>
</tr>
IF:parent
<tr>
<td>Parent:</td>
<td>
IF:par_url
<a href="%par_url%">
ENDIF:par_url
%parent%
IF:par_url
</a>
ENDIF:par_url
</td>
</tr>
ENDIF:parent
</table>
</td>
</tr>
</table>
HTML
###################################################################
METHOD_LIST = <<HTML
<div id="content">
IF:diagram
<table cellpadding='0' cellspacing='0' border='0' width="100%"><tr><td align="center">
%diagram%
</td></tr></table>
ENDIF:diagram
IF:description
<div class="description">%description%</div>
ENDIF:description
IF:requires
<div class="sectiontitle">Required Files</div>
<ul>
START:requires
<li>HREF:aref:name:</li>
END:requires
</ul>
ENDIF:requires
IF:toc
<div class="sectiontitle">Contents</div>
<ul>
START:toc
<li><a href="#%href%">%secname%</a></li>
END:toc
</ul>
ENDIF:toc
IF:methods
<div class="sectiontitle">Methods</div>
<ul>
START:methods
<li>HREF:aref:name:</li>
END:methods
</ul>
ENDIF:methods
IF:includes
<div class="sectiontitle">Included Modules</div>
<ul>
START:includes
<li>HREF:aref:name:</li>
END:includes
</ul>
ENDIF:includes
START:sections
IF:sectitle
<div class="sectiontitle"><a nem="%secsequence%">%sectitle%</a></div>
IF:seccomment
<div class="description">
%seccomment%
</div>
ENDIF:seccomment
ENDIF:sectitle
IF:classlist
<div class="sectiontitle">Classes and Modules</div>
%classlist%
ENDIF:classlist
IF:constants
<div class="sectiontitle">Constants</div>
<table border='0' cellpadding='5'>
START:constants
<tr valign='top'>
<td class="attr-name">%name%</td>
<td>=</td>
<td class="attr-value">%value%</td>
</tr>
IF:desc
<tr valign='top'>
<td>&nbsp;</td>
<td colspan="2" class="attr-desc">%desc%</td>
</tr>
ENDIF:desc
END:constants
</table>
ENDIF:constants
IF:attributes
<div class="sectiontitle">Attributes</div>
<table border='0' cellpadding='5'>
START:attributes
<tr valign='top'>
<td class='attr-rw'>
IF:rw
[%rw%]
ENDIF:rw
</td>
<td class='attr-name'>%name%</td>
<td class='attr-desc'>%a_desc%</td>
</tr>
END:attributes
</table>
ENDIF:attributes
IF:method_list
START:method_list
IF:methods
<div class="sectiontitle">%type% %category% methods</div>
START:methods
<div class="method">
<div class="title">
IF:callseq
<a name="%aref%"></a><b>%callseq%</b>
ENDIF:callseq
IFNOT:callseq
<a name="%aref%"></a><b>%name%</b>%params%
ENDIF:callseq
IF:codeurl
[ <a href="javascript:openCode('%codeurl%')">source</a> ]
ENDIF:codeurl
</div>
IF:m_desc
<div class="description">
%m_desc%
</div>
ENDIF:m_desc
IF:aka
<div class="aka">
This method is also aliased as
START:aka
<a href="%aref%">%name%</a>
END:aka
</div>
ENDIF:aka
IF:sourcecode
<div class="sourcecode">
<p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
<div id="%aref%_source" class="dyn-source">
<pre>
%sourcecode%
</pre>
</div>
</div>
ENDIF:sourcecode
</div>
END:methods
ENDIF:methods
END:method_list
ENDIF:method_list
END:sections
</div>
HTML
FOOTER = <<ENDFOOTER
</body>
</html>
ENDFOOTER
BODY = HEADER + <<ENDBODY
!INCLUDE! <!-- banner header -->
<div id="bodyContent">
#{METHOD_LIST}
</div>
#{FOOTER}
ENDBODY
########################## Source code ##########################
SRC_PAGE = XHTML_PREAMBLE + <<HTML
<html>
<head><title>%title%</title>
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
<style>
.ruby-comment { color: green; font-style: italic }
.ruby-constant { color: #4433aa; font-weight: bold; }
.ruby-identifier { color: #222222; }
.ruby-ivar { color: #2233dd; }
.ruby-keyword { color: #3333FF; font-weight: bold }
.ruby-node { color: #777777; }
.ruby-operator { color: #111111; }
.ruby-regexp { color: #662222; }
.ruby-value { color: #662222; font-style: italic }
.kw { color: #3333FF; font-weight: bold }
.cmt { color: green; font-style: italic }
.str { color: #662222; font-style: italic }
.re { color: #662222; }
</style>
</head>
<body bgcolor="white">
<pre>%code%</pre>
</body>
</html>
HTML
########################## Index ################################
FR_INDEX_BODY = <<HTML
!INCLUDE!
HTML
FILE_INDEX = XHTML_PREAMBLE + <<HTML
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
<style>
<!--
body {
background-color: #EEE;
font-family: #{FONTS};
color: #000;
margin: 0px;
}
.banner {
background: #005;
color: #FFF;
padding: 0.2em;
font-size: small;
font-weight: bold;
text-align: center;
}
.entries {
margin: 0.25em 1em 0 1em;
font-size: x-small;
}
a {
color: #00F;
text-decoration: none;
white-space: nowrap;
}
a:hover {
color: #77F;
text-decoration: underline;
}
-->
</style>
<base target="docwin">
</head>
<body>
<div class="banner">%list_title%</div>
<div class="entries">
START:entries
<a href="%href%">%name%</a><br>
END:entries
</div>
</body></html>
HTML
CLASS_INDEX = FILE_INDEX
METHOD_INDEX = FILE_INDEX
INDEX = XHTML_PREAMBLE + <<HTML
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>%title%</title>
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
</head>
<frameset cols="20%,*">
<frameset rows="15%,35%,50%">
<frame src="fr_file_index.html" title="Files" name="Files" />
<frame src="fr_class_index.html" name="Classes" />
<frame src="fr_method_index.html" name="Methods" />
</frameset>
IF:inline_source
<frame src="%initial_page%" name="docwin">
ENDIF:inline_source
IFNOT:inline_source
<frameset rows="80%,20%">
<frame src="%initial_page%" name="docwin">
<frame src="blank.html" name="source">
</frameset>
ENDIF:inline_source
<noframes>
<body bgcolor="white">
Click <a href="html/index.html">here</a> for a non-frames
version of this page.
</body>
</noframes>
</frameset>
</html>
HTML
end
end

127
doc/rake/proto_rake.rdoc Normal file
View file

@ -0,0 +1,127 @@
= Original Prototype Rake
This is the original 100 line prototype rake program.
---
#!/usr/bin/env ruby
require 'ftools'
class Task
TASKS = Hash.new
attr_reader :prerequisites
def initialize(task_name)
@name = task_name
@prerequisites = []
@actions = []
end
def enhance(deps=nil, &block)
@prerequisites |= deps if deps
@actions << block if block_given?
self
end
def name
@name.to_s
end
def invoke
@prerequisites.each { |n| Task[n].invoke }
execute if needed?
end
def execute
return if @triggered
@triggered = true
@actions.collect { |act| result = act.call(self) }.last
end
def needed?
true
end
def timestamp
Time.now
end
class << self
def [](task_name)
TASKS[intern(task_name)] or fail "Don't know how to rake #{task_name}"
end
def define_task(args, &block)
case args
when Hash
fail "Too Many Target Names: #{args.keys.join(' ')}" if args.size > 1
fail "No Task Name Given" if args.size < 1
task_name = args.keys[0]
deps = args[task_name]
else
task_name = args
deps = []
end
deps = deps.collect {|d| intern(d) }
get(task_name).enhance(deps, &block)
end
def get(task_name)
name = intern(task_name)
TASKS[name] ||= self.new(name)
end
def intern(task_name)
(Symbol === task_name) ? task_name : task_name.intern
end
end
end
class FileTask < Task
def needed?
return true unless File.exist?(name)
latest_prereq = @prerequisites.collect{|n| Task[n].timestamp}.max
return false if latest_prereq.nil?
timestamp < latest_prereq
end
def timestamp
File.new(name.to_s).mtime
end
end
def task(args, &block)
Task.define_task(args, &block)
end
def file(args, &block)
FileTask.define_task(args, &block)
end
def sys(cmd)
puts cmd
system(cmd) or fail "Command Failed: [#{cmd}]"
end
def rake
begin
here = Dir.pwd
while ! File.exist?("Rakefile")
Dir.chdir("..")
fail "No Rakefile found" if Dir.pwd == here
here = Dir.pwd
end
puts "(in #{Dir.pwd})"
load "./Rakefile"
ARGV.push("default") if ARGV.size == 0
ARGV.each { |task_name| Task[task_name].invoke }
rescue Exception => ex
puts "rake aborted ... #{ex.message}"
puts ex.backtrace.find {|str| str =~ /Rakefile/ } || ""
end
end
if __FILE__ == $0 then
rake
end

534
doc/rake/rakefile.rdoc Normal file
View file

@ -0,0 +1,534 @@
= Rakefile Format (as of version 0.8.3)
First of all, there is no special format for a Rakefile. A Rakefile
contains executable Ruby code. Anything legal in a ruby script is
allowed in a Rakefile.
Now that we understand there is no special syntax in a Rakefile, there
are some conventions that are used in a Rakefile that are a little
unusual in a typical Ruby program. Since a Rakefile is tailored to
specifying tasks and actions, the idioms used in a Rakefile are
designed to support that.
So, what goes into a Rakefile?
== Tasks
Tasks are the main unit of work in a Rakefile. Tasks have a name
(usually given as a symbol or a string), a list of prerequisites (more
symbols or strings) and a list of actions (given as a block).
=== Simple Tasks
A task is declared by using the +task+ method. +task+ takes a single
parameter that is the name of the task.
task :name
=== Tasks with Prerequisites
Any prerequisites are given as a list (inclosed in square brackets)
following the name and an arrow (=>).
task :name => [:prereq1, :prereq2]
<b>NOTE:</b> Although this syntax looks a little funky, it is legal
Ruby. We are constructing a hash where the key is :name and the value
for that key is the list of prerequisites. It is equivalent to the
following ...
hash = Hash.new
hash[:name] = [:prereq1, :prereq2]
task(hash)
=== Tasks with Actions
Actions are defined by passing a block to the +task+ method. Any Ruby
code can be placed in the block. The block may reference the task
object via the block paramter..
task :name => [:prereq1, :prereq2] do |t|
# actions (may reference t)
end
=== Multiple Definitions
A task may be specified more than once. Each specification adds its
prerequisites and actions to the existing definition. This allows one
part of a rakefile to specify the actions and a different rakefile
(perhaps separately generated) to specify the dependencies.
For example, the following is equivalent to the single task
specification given above.
task :name
task :name => [:prereq1]
task :name => [:prereq2]
task :name do |t|
# actions
end
== File Tasks
Some tasks are designed to create a file from one or more other files.
Tasks that generate these files may be skipped if the file already
exists. File tasks are used to specify file creation tasks.
File tasks are declared using the +file+ method (instead of the +task+
method). In addition, file tasks are usually named with a string
rather than a symbol.
The following file task creates a executable program (named +prog+)
given two object files name <tt>a.o</tt> and <tt>b.o</tt>. The tasks
for creating <tt>a.o</tt> and <tt>b.o</tt> are not shown.
file "prog" => ["a.o", "b.o"] do |t|
sh "cc -o #{t.name} #{t.prerequisites.join(' ')}"
end
== Directory Tasks
It is common to need to create directories upon demand. The
+directory+ convenience method is a short-hand for creating a FileTask
that creates the directory. For example, the following declaration
...
directory "testdata/examples/doc"
is equivalent to ...
file "testdata" do |t| mkdir t.name end
file "testdata/examples" do |t| mkdir t.name end
file "testdata/examples/doc" do |t| mkdir t.name end
The +directory+ method does not accept prerequisites or actions, but
both prerequisites and actions can be added later. For example ...
directory "testdata"
file "testdata" => ["otherdata"]
file "testdata" do
cp Dir["standard_data/*.data"], "testdata"
end
== Tasks with Parallel Prerequisites
Rake allows parallel execution of prerequisites using the following syntax:
multitask :copy_files => [:copy_src, :copy_doc, :copy_bin] do
puts "All Copies Complete"
end
In this example, +copy_files+ is a normal rake task. Its actions are
executed whereever all of its prerequisites are done. The big
difference is that the prerequisites (+copy_src+, +copy_bin+ and
+copy_doc+) are executed in parallel. Each of the prerequisites are
run in their own Ruby thread, possibly allowing faster overall runtime.
=== Secondary Prerequisites
If any of the primary prerequites of a multitask have common secondary
prerequisites, all of the primary/parallel prerequisites will wait
until the common prerequisites have been run.
For example, if the <tt>copy_<em>xxx</em></tt> tasks have the
following prerequisites:
task :copy_src => [:prep_for_copy]
task :copy_bin => [:prep_for_copy]
task :copy_doc => [:prep_for_copy]
Then the +prep_for_copy+ task is run before starting all the copies in
parallel. Once +prep_for_copy+ is complete, +copy_src+, +copy_bin+,
and +copy_doc+ are all run in parallel. Note that +prep_for_copy+ is
run only once, even though it is referenced in multiple threads.
=== Thread Safety
The Rake internal data structures are thread-safe with respect
to the multitask parallel execution, so there is no need for the user
to do extra synchronization for Rake's benefit. However, if there are
user data structures shared between the parallel prerequisites, the
user must do whatever is necessary to prevent race conditions.
== Tasks with Arguments
Prior to version 0.8.0, rake was only able to handle command line
arguments of the form NAME=VALUE that were passed into Rake via the
ENV hash. Many folks had asked for some kind of simple command line
arguments, perhaps using "--" to separate regular task names from
argument values on the command line. The problem is that there was no
easy way to associate positional arguments on the command line with
different tasks. Suppose both tasks :a and :b expect a command line
argument: does the first value go with :a? What if :b is run first?
Should it then get the first command line argument.
Rake 0.8.0 solves this problem by explicitly passing values directly
to the tasks that need them. For example, if I had a release task
that required a version number, I could say:
rake release[0.8.2]
And the string "0.8.2" will be passed to the :release task. Multiple
arguments can be passed by separating them with a comma, for example:
rake name[john,doe]
Just a few words of caution. The rake task name and its arguments
need to be a single command line argument to rake. This generally
means no spaces. If spaces are needed, then the entire rake +
argument string should be quoted. Something like this:
rake "name[billy bob, smith]"
(Quoting rules vary between operating systems and shells, so make sure
you consult the proper docs for your OS/shell).
=== Tasks that Expect Parameters
Parameters are only given to tasks that are setup to expect them. In
order to handle named parameters, the task declaration syntax for
tasks has been extended slightly.
For example, a task that needs a first name and last name might be
declared as:
task :name, [:first_name, :last_name]
The first argument is still the name of the task (:name in this case).
The next to argumements are the names of the parameters expected by
:name in an array (:first_name and :last_name in the example).
To access the values of the paramters, the block defining the task
behaviour can now accept a second parameter:
task :name, [:first_name, :last_name] do |t, args|
puts "First name is #{args.first_name}"
puts "Last name is #{args.last_name}"
end
The first argument of the block "t" is always bound to the current
task object. The second argument "args" is an open-struct like object
that allows access to the task arguments. Extra command line
arguments to a task are ignored. Missing command line arguments are
given the nil value.
If you wish to specify default values for the arguments, you can use
the with_defaults method in the task body. Here is the above example
where we specify default values for the first and last names:
task :name, [:first_name, :last_name] do |t, args|
args.with_defaults(:first_name => "John", :last_name => "Dough")
puts "First name is #{args.first_name}"
puts "Last name is #{args.last_name}"
end
=== Tasks that Expect Parameters and Have Prerequisites
Tasks that use parameters have a slightly different format for
prerequisites. Use the arrow notation to indicate the prerequisites
for tasks with arguments. For example:
task :name, [:first_name, :last_name] => [:pre_name] do |t, args|
args.with_defaults(:first_name => "John", :last_name => "Dough")
puts "First name is #{args.first_name}"
puts "Last name is #{args.last_name}"
end
=== Deprecated Task Parameters Format
There is an older format for declaring task parameters that omitted
the task argument array and used the :needs keyword to introduce the
dependencies. That format is still supported for compatibility, but
is not recommended for use.
== Accessing Task Programatically
Sometimes it is useful to manipulate tasks programatically in a
Rakefile. To find a task object, use the <tt>:[]</tt> operator on the
<tt>Rake::Task</tt>.
=== Programmatic Task Example
For example, the following Rakefile defines two tasks. The :doit task
simply prints a simple "DONE" message. The :dont class will lookup
the doit class and remove (clear) all of its prerequisites and
actions.
task :doit do
puts "DONE"
end
task :dont do
Rake::Task[:doit].clear
end
Running this example:
$ rake doit
(in /Users/jim/working/git/rake/x)
DONE
$ rake dont doit
(in /Users/jim/working/git/rake/x)
$
The ability to programmatically manipulate tasks gives rake very
powerful meta-programming capabilities w.r.t. task execution, but
should be used with cation.
== Rules
When a file is named as a prerequisite, but does not have a file task
defined for it, Rake will attempt to synthesize a task by looking at a
list of rules supplied in the Rakefile.
Suppose we were trying to invoke task "mycode.o", but no task is
defined for it. But the rakefile has a rule that look like this ...
rule '.o' => ['.c'] do |t|
sh "cc #{t.source} -c -o #{t.name}"
end
This rule will synthesize any task that ends in ".o". It has a
prerequisite a source file with an extension of ".c" must exist. If
Rake is able to find a file named "mycode.c", it will automatically
create a task that builds "mycode.o" from "mycode.c".
If the file "mycode.c" does not exist, rake will attempt
to recursively synthesize a rule for it.
When a task is synthesized from a rule, the +source+ attribute of the
task is set to the matching source file. This allows us to write
rules with actions that reference the source file.
=== Advanced Rules
Any regular expression may be used as the rule pattern. Additionally,
a proc may be used to calculate the name of the source file. This
allows for complex patterns and sources.
The following rule is equivalent to the example above.
rule( /\.o$/ => [
proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') }
]) do |t|
sh "cc #{t.source} -c -o #{t.name}"
end
<b>NOTE:</b> Because of a _quirk_ in Ruby syntax, parenthesis are
required on *rule* when the first argument is a regular expression.
The following rule might be used for Java files ...
rule '.java' => [
proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') }
] do |t|
java_compile(t.source, t.name)
end
<b>NOTE:</b> +java_compile+ is a hypothetical method that invokes the
java compiler.
== Importing Dependencies
Any ruby file (including other rakefiles) can be included with a
standard Ruby +require+ command. The rules and declarations in the
required file are just added to the definitions already accumulated.
Because the files are loaded _before_ the rake targets are evaluated,
the loaded files must be "ready to go" when the rake command is
invoked. This make generated dependency files difficult to use. By
the time rake gets around to updating the dependencies file, it is too
late to load it.
The +import+ command addresses this by specifying a file to be loaded
_after_ the main rakefile is loaded, but _before_ any targets on the
command line are specified. In addition, if the file name matches an
explicit task, that task is invoked before loading the file. This
allows dependency files to be generated and used in a single rake
command invocation.
=== Example:
require 'rake/loaders/makefile'
file ".depends.mf" => [SRC_LIST] do |t|
sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}"
end
import ".depends.mf"
If ".depends" does not exist, or is out of date w.r.t. the source
files, a new ".depends" file is generated using +makedepend+ before
loading.
== Comments
Standard Ruby comments (beginning with "#") can be used anywhere it is
legal in Ruby source code, including comments for tasks and rules.
However, if you wish a task to be described using the "-T" switch,
then you need to use the +desc+ command to describe the task.
=== Example:
desc "Create a distribution package"
task :package => [ ... ] do ... end
The "-T" switch (or "--tasks" if you like to spell things out) will
display a list of tasks that have a defined comment. If you use
+desc+ to describe your major tasks, you have a semi-automatic way of
generating a summary of your Rake file.
traken$ rake -T
(in /home/.../rake)
rake clean # Remove any temporary products.
rake clobber # Remove any generated file.
rake clobber_rdoc # Remove rdoc products
rake contrib_test # Run tests for contrib_test
rake default # Default Task
rake install # Install the application
rake lines # Count lines in the main rake file
rake rdoc # Build the rdoc HTML Files
rake rerdoc # Force a rebuild of the RDOC files
rake test # Run tests
rake testall # Run all test targets
Only tasks with descriptions will be displayed with the "-T" switch.
Use "-P" (or "--prereqs") to get a list of all tasks and their
prerequisites.
== Namespaces
As projects grow (and along with it, the number of tasks), it is
common for task names to begin to clash. For example, if you might
have a main program and a set of sample programs built by a single
Rakefile. By placing the tasks related to the main program in one
namespace, and the tasks for building the sample programs in a
different namespace, the task names will not will not interfer with
each other.
For example:
namespace "main"
task :build do
# Build the main program
end
end
namespace "samples" do
task :build do
# Build the sample programs
end
end
task :build => ["main:build", "samples:build"]
Referencing a task in a separate namespace can be achieved by
prefixing the task name with the namespace and a colon
(e.g. "main:build" refers to the :build task in the +main+ namespace).
Nested namespaces are supported, so
Note that the name given in the +task+ command is always the unadorned
task name without any namespace prefixes. The +task+ command always
defines a task in the current namespace.
=== FileTasks
File task names are not scoped by the namespace command. Since the
name of a file task is the name of an actual file in the file system,
it makes little sense to include file task names in name space.
Directory tasks (created by the +directory+ command) are a type of
file task and are also not affected by namespaces.
=== Name Resolution
When looking up a task name, rake will start with the current
namespace and attempt to find the name there. If it fails to find a
name in the current namespace, it will search the parent namespaces
until a match is found (or an error occurs if there is no match).
The "rake" namespace is a special implicit namespace that refers to
the toplevel names.
If a task name begins with a "^" character, the name resolution will
start in the parent namespace. Multiple "^" characters are allowed.
Here is an example file with multiple :run tasks and how various names
resolve in different locations.
task :run
namespace "one" do
task :run
namespace "two" do
task :run
# :run => "one:two:run"
# "two:run" => "one:two:run"
# "one:two:run" => "one:two:run"
# "one:run" => "one:run"
# "^run" => "one:run"
# "^^run" => "rake:run" (the top level task)
# "rake:run" => "rake:run" (the top level task)
end
# :run => "one:run"
# "two:run" => "one:two:run"
# "^run" => "rake:run"
end
# :run => "rake:run"
# "one:run" => "one:run"
# "one:two:run" => "one:two:run"
== FileLists
FileLists are the way Rake manages lists of files. You can treat a
FileList as an array of strings for the most part, but FileLists
support some additional operations.
=== Creating a FileList
Creating a file list is easy. Just give it the list of file names:
fl = FileList['file1.rb', file2.rb']
Or give it a glob pattern:
fl = FileList['*.rb']
== Odds and Ends
=== do/end verses { }
Blocks may be specified with either a +do+/+end+ pair, or with curly
braces in Ruby. We _strongly_ recommend using +do+/+end+ to specify the
actions for tasks and rules. Because the rakefile idiom tends to
leave off parenthesis on the task/file/rule methods, unusual
ambiguities can arise when using curly braces.
For example, suppose that the method +object_files+ returns a list of
object files in a project. Now we use +object_files+ as the
prerequistes in a rule specified with actions in curly braces.
# DON'T DO THIS!
file "prog" => object_files {
# Actions are expected here (but it doesn't work)!
}
Because curly braces have a higher precedence than +do+/+end+, the
block is associated with the +object_files+ method rather than the
+file+ method.
This is the proper way to specify the task ...
# THIS IS FINE
file "prog" => object_files do
# Actions go here
end
----
== See
* README -- Main documentation for Rake.

151
doc/rake/rational.rdoc Normal file
View file

@ -0,0 +1,151 @@
= Why rake?
Ok, let me state from the beginning that I never intended to write this
code. I'm not convinced it is useful, and I'm not convinced anyone
would even be interested in it. All I can say is that Why's onion truck
must by been passing through the Ohio valley.
What am I talking about? ... A Ruby version of Make.
See, I can sense you cringing already, and I agree. The world certainly
doesn't need yet another reworking of the "make" program. I mean, we
already have "ant". Isn't that enough?
It started yesterday. I was helping a coworker fix a problem in one of
the Makefiles we use in our project. Not a particularly tough problem,
but during the course of the conversation I began lamenting some of the
shortcomings of make. In particular, in one of my makefiles I wanted to
determine the name of a file dynamically and had to resort to some
simple scripting (in Ruby) to make it work. "Wouldn't it be nice if you
could just use Ruby inside a Makefile" I said.
My coworker (a recent convert to Ruby) agreed, but wondered what it
would look like. So I sketched the following on the whiteboard...
"What if you could specify the make tasks in Ruby, like this ..."
task "build" do
java_compile(...args, etc ...)
end
"The task function would register "build" as a target to be made,
and the block would be the action executed whenever the build
system determined that it was time to do the build target."
We agreed that would be cool, but writing make from scratch would be WAY
too much work. And that was the end of that!
... Except I couldn't get the thought out of my head. What exactly
would be needed to make the about syntax work as a make file? Hmmm, you
would need to register the tasks, you need some way of specifying
dependencies between tasks, and some way of kicking off the process.
Hey! What if we did ... and fifteen minutes later I had a working
prototype of Ruby make, complete with dependencies and actions.
I showed the code to my coworker and we had a good laugh. It was just
about a page worth of code that reproduced an amazing amount of the
functionality of make. We were both truely stunned with the power of
Ruby.
But it didn't do everything make did. In particular, it didn't have
timestamp based file dependencies (where a file is rebuilt if any of its
prerequisite files have a later timestamp). Obviously THAT would be a
pain to add and so Ruby Make would remain an interesting experiment.
... Except as I walked back to my desk, I started thinking about what
file based dependecies would really need. Rats! I was hooked again,
and by adding a new class and two new methods, file/timestamp
dependencies were implemented.
Ok, now I was really hooked. Last night (during CSI!) I massaged the
code and cleaned it up a bit. The result is a bare-bones replacement
for make in exactly 100 lines of code.
For the curious, you can see it at ...
* doc/proto_rake.rdoc
Oh, about the name. When I wrote the example Ruby Make task on my
whiteboard, my coworker exclaimed "Oh! I have the perfect name: Rake ...
Get it? Ruby-Make. Rake!" He said he envisioned the tasks as leaves
and Rake would clean them up ... or something like that. Anyways, the
name stuck.
Some quick examples ...
A simple task to delete backup files ...
task :clean do
Dir['*~'].each {|fn| rm fn rescue nil}
end
Note that task names are symbols (they are slightly easier to type
than quoted strings ... but you may use quoted string if you would
rather). Rake makes the methods of the FileUtils module directly
available, so we take advantage of the <tt>rm</tt> command. Also note
the use of "rescue nil" to trap and ignore errors in the <tt>rm</tt>
command.
To run it, just type "rake clean". Rake will automatically find a
Rakefile in the current directory (or above!) and will invoke the
targets named on the command line. If there are no targets explicitly
named, rake will invoke the task "default".
Here's another task with dependencies ...
task :clobber => [:clean] do
rm_r "tempdir"
end
Task :clobber depends upon task :clean, so :clean will be run before
:clobber is executed.
Files are specified by using the "file" command. It is similar to the
task command, except that the task name represents a file, and the task
will be run only if the file doesn't exist, or if its modification time
is earlier than any of its prerequisites.
Here is a file based dependency that will compile "hello.cc" to
"hello.o".
file "hello.cc"
file "hello.o" => ["hello.cc"] do |t|
srcfile = t.name.sub(/\.o$/, ".cc")
sh %{g++ #{srcfile} -c -o #{t.name}}
end
I normally specify file tasks with string (rather than symbols). Some
file names can't be represented by symbols. Plus it makes the
distinction between them more clear to the casual reader.
Currently writing a task for each and every file in the project would be
tedious at best. I envision a set of libraries to make this job
easier. For instance, perhaps something like this ...
require 'rake/ctools'
Dir['*.c'].each do |fn|
c_source_file(fn)
end
where "c_source_file" will create all the tasks need to compile all the
C source files in a directory. Any number of useful libraries could be
created for rake.
That's it. There's no documentation (other than whats in this
message). Does this sound interesting to anyone? If so, I'll continue
to clean it up and write it up and publish it on RAA. Otherwise, I'll
leave it as an interesting excerise and a tribute to the power of Ruby.
Why /might/ rake be interesting to Ruby programmers. I don't know,
perhaps ...
* No weird make syntax (only weird Ruby syntax :-)
* No need to edit or read XML (a la ant)
* Platform independent build scripts.
* Will run anywhere Ruby exists, so no need to have "make" installed.
If you stay away from the "sys" command and use things like
'ftools', you can have a perfectly platform independent
build script. Also rake is only 100 lines of code, so it can
easily be packaged along with the rest of your code.
So ... Sorry for the long rambling message. Like I said, I never
intended to write this code at all.

View file

@ -0,0 +1,55 @@
= Rake 0.8.7 Released
Rake version 0.8.5 introduced greatly improved support for executing
commands on Windows. The "sh" command now has the same semantics on
Windows that it has on Unix based platforms.
Rake version 0.8.6 includes minor fixes the the RDoc generation.
Rake version 0.8.7 includes a minor fix for JRuby running on windows.
== Changes
=== New Features / Enhancements in Version 0.8.5
* Improved implementation of the Rake system command for Windows.
(patch from James M. Lawrence/quix)
* Support for Ruby 1.9's improved system command. (patch from James
M. Lawrence/quix)
* Rake now includes the configured extension when invoking an
executable (Config::CONFIG['EXEEXT])
=== Bug Fixes in Version 0.8.5
* Environment variable keys are now correctly cased (it matters in
some implementations).
== What is Rake
Rake is a build tool similar to the make program in many ways. But
instead of cryptic make recipes, Rake uses standard Ruby code to
declare tasks and dependencies. You have the full power of a modern
scripting language built right into your build tool.
== Availability
The easiest way to get and install rake is via RubyGems ...
gem install rake (you may need root/admin privileges)
Otherwise, you can get it from the more traditional places:
Home Page:: http://rake.rubyforge.org/
Download:: http://rubyforge.org/project/showfiles.php?group_id=50
GitHub:: git://github.com/jimweirich/rake.git
== Thanks
As usual, it was input from users that drove a alot of these changes. The
following people either contributed patches, made suggestions or made
otherwise helpful comments. Thanks to ...
* Charles Nutter
-- Jim Weirich

View file

@ -27,7 +27,7 @@
# as a library via a require statement, but it can be distributed
# independently as an application.
RAKEVERSION = '0.8.4'
RAKEVERSION = '0.8.7'
require 'rbconfig'
require 'fileutils'
@ -38,6 +38,8 @@ require 'ostruct'
require 'rake/win32'
$trace = false
######################################################################
# Rake extensions to Module.
#
@ -201,7 +203,7 @@ class String
when '%f'
result << File.basename(self)
when '%n'
result << File.basename(self, '.*')
result << File.basename(self).ext
when '%d'
result << File.dirname(self)
when '%x'
@ -278,7 +280,7 @@ module Rake
end
# ##########################################################################
####################################################################
# Mixin for creating easily cloned objects.
#
module Cloneable
@ -302,6 +304,27 @@ module Rake
end
end
####################################################################
# Exit status class for times the system just gives us a nil.
class PseudoStatus
attr_reader :exitstatus
def initialize(code=0)
@exitstatus = code
end
def to_i
@exitstatus << 8
end
def >>(n)
to_i >> n
end
def stopped?
false
end
def exited?
true
end
end
####################################################################
# TaskAguments manage the arguments passed to a task.
#
@ -432,7 +455,7 @@ end # module Rake
module Rake
# #########################################################################
###########################################################################
# A Task is the basic unit of work in a Rakefile. Tasks have associated
# actions (possibly more than one) and a list of prerequisites. When
# invoked, a task will first ensure that all of its prerequisites have an
@ -732,7 +755,7 @@ module Rake
end # class Rake::Task
# #########################################################################
###########################################################################
# A FileTask is a task that includes time based dependencies. If any of a
# FileTask's prerequisites have a timestamp that is later than the file
# represented by this task, then the file must be rebuilt (using the
@ -774,7 +797,7 @@ module Rake
end
end # class Rake::FileTask
# #########################################################################
###########################################################################
# A FileCreationTask is a file task that when used as a dependency will be
# needed if and only if the file has not been created. Once created, it is
# not re-triggered if any of its dependencies are newer, nor does trigger
@ -793,7 +816,7 @@ module Rake
end
end
# #########################################################################
###########################################################################
# Same as a regular task, but the immediate prerequisites are done in
# parallel using Ruby threads.
#
@ -808,7 +831,7 @@ module Rake
end
end # module Rake
# ###########################################################################
## ###########################################################################
# Task Definition Functions ...
# Declare a basic task.
@ -927,12 +950,18 @@ def import(*fns)
end
end
# ###########################################################################
#############################################################################
# This a FileUtils extension that defines several additional commands to be
# added to the FileUtils utility functions.
#
module FileUtils
RUBY = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']).
RUBY_EXT = ((RbConfig::CONFIG['ruby_install_name'] =~ /\.(com|cmd|exe|bat|rb|sh)$/) ?
"" :
RbConfig::CONFIG['EXEEXT'])
RUBY = File.join(
RbConfig::CONFIG['bindir'],
RbConfig::CONFIG['ruby_install_name'] + RUBY_EXT).
sub(/.*\s.*/m, '"\&"')
OPT_TABLE['sh'] = %w(noop verbose)
@ -958,7 +987,7 @@ module FileUtils
options = (Hash === cmd.last) ? cmd.pop : {}
unless block_given?
show_command = cmd.join(" ")
show_command = show_command[0,42] + "..."
show_command = show_command[0,42] + "..." unless $trace
# TODO code application logic heref show_command.length > 45
block = lambda { |ok, status|
ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
@ -974,7 +1003,9 @@ module FileUtils
rake_output_message cmd.join(" ") if options[:verbose]
unless options[:noop]
res = rake_system(*cmd)
block.call(res, $?)
status = $?
status = PseudoStatus.new(1) if !res && status.nil?
block.call(res, status)
end
end
@ -1027,7 +1058,7 @@ module FileUtils
end
end
# ###########################################################################
#############################################################################
# RakeFileUtils provides a custom version of the FileUtils methods that
# respond to the <tt>verbose</tt> and <tt>nowrite</tt> commands.
#
@ -1158,7 +1189,7 @@ module RakeFileUtils
extend self
end
# ###########################################################################
#############################################################################
# Include the FileUtils file manipulation functions in the top level module,
# but mark them private so that they don't unintentionally define methods on
# other objects.
@ -1170,7 +1201,7 @@ private(*RakeFileUtils.instance_methods(false))
######################################################################
module Rake
# #########################################################################
###########################################################################
# A FileList is essentially an array with a few helper methods defined to
# make file manipulation a bit easier.
#
@ -1228,21 +1259,17 @@ module Rake
# Now do the delegation.
DELEGATING_METHODS.each_with_index do |sym, i|
if SPECIAL_RETURN.include?(sym)
class_eval <<-END, __FILE__, __LINE__+1
def #{sym}(*args, &block)
resolve
result = @items.send(:#{sym}, *args, &block)
FileList.new.import(result)
end
END
define_method(sym) do |*args, &block|
resolve
result = @items.send(sym, *args, &block)
FileList.new.import(result)
end
else
class_eval <<-END, __FILE__, __LINE__+1
def #{sym}(*args, &block)
resolve
result = @items.send(:#{sym}, *args, &block)
result.object_id == @items.object_id ? self : result
end
END
define_method(sym) do |*args, &block|
resolve
result = @items.send(sym, *args, &block)
result.object_id == @items.object_id ? self : result
end
end
end
@ -1450,7 +1477,7 @@ module Rake
collect { |fn| fn.pathmap(spec) }
end
# Return a new file list with <tt>String#ext</tt> method applied
# Return a new FileList with <tt>String#ext</tt> method applied
# to each member of the array.
#
# This method is a shortcut for:
@ -1468,9 +1495,9 @@ module Rake
# name, line number, and the matching line of text. If no block is given,
# a standard emac style file:linenumber:line message will be printed to
# standard out.
def egrep(pattern, *opt)
def egrep(pattern, *options)
each do |fn|
open(fn, "rb", *opt) do |inf|
open(fn, "rb", *options) do |inf|
count = 0
inf.each do |line|
count += 1
@ -1576,7 +1603,7 @@ end # module Rake
# Alias FileList to be available at the top level.
FileList = Rake::FileList
# ###########################################################################
#############################################################################
module Rake
# Default Rakefile loader used by +import+.
@ -1603,7 +1630,7 @@ module Rake
EARLY = EarlyTime.instance
end # module Rake
# ###########################################################################
#############################################################################
# Extensions to time to allow comparisons with an early time class.
#
class Time
@ -1960,11 +1987,9 @@ module Rake
# application. The define any tasks. Finally, call +top_level+ to run your top
# level tasks.
def run
standard_exception_handling do
init
load_rakefile
top_level
end
init
load_rakefile
top_level
end
# Initialize the command line parameters and app name.
@ -2041,7 +2066,7 @@ module Rake
# Exit with error message
$stderr.puts "#{name} aborted!"
$stderr.puts ex.message
if options.trace
if options.trace or true
$stderr.puts ex.backtrace.join("\n")
else
$stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
@ -2362,24 +2387,13 @@ module Rake
# The directory path containing the system wide rakefiles.
def system_dir
@system_dir ||=
begin
if ENV['RAKE_SYSTEM']
ENV['RAKE_SYSTEM']
else
standard_system_dir
end
end
@system_dir ||= ENV['RAKE_SYSTEM'] || standard_system_dir
end
# The standard directory containing system wide rake files.
if Win32.windows?
unless method_defined?(:standard_system_dir)
def standard_system_dir #:nodoc:
Win32.win32_system_dir
end
else
def standard_system_dir #:nodoc:
File.expand_path('.rake', '~')
File.expand_path('~/.rake')
end
end
private :standard_system_dir

View file

@ -21,7 +21,7 @@ module Rake
def process_line(line)
file_tasks, args = line.split(':', 2)
return if args.nil?
dependents = args.split
dependents = args.split.map {|arg| respace(arg)}
file_tasks.scan(/\S+/) do |file_task|
file_task = respace(file_task)
file file_task => dependents

View file

@ -19,7 +19,7 @@ module Rake
# Rebuild the rdoc files from scratch, even if they are not out
# of date.
#
# Simple example:
# Simple Example:
#
# Rake::RDocTask.new do |rd|
# rd.main = "README.rdoc"
@ -132,7 +132,7 @@ module Rake
args = option_list + @rdoc_files
if @external
argstring = args.join(' ')
sh %{ruby -Ivendor vender/rd #{argstring}}
sh %{ruby -Ivendor vendor/rd #{argstring}}
else
require 'rdoc/rdoc'
RDoc::RDoc.new.document(args)

View file

@ -93,7 +93,7 @@ module Rake
# Create the tasks defined by this task lib.
def define
lib_path = @libs.collect {|path| "-I#{File.expand_path(path)}"}
lib_path = @libs.join(File::PATH_SEPARATOR)
desc "Run tests" + (@name==:test ? "" : " for #{@name}")
task @name do
run_code = ''
@ -103,11 +103,11 @@ module Rake
when :direct
"-e 'ARGV.each{|f| load f}'"
when :testrb
"-S testrb #{fix}"
"-S testrb"
when :rake
rake_loader
end
@ruby_opts.unshift( *lib_path )
@ruby_opts.unshift( "-I\"#{lib_path}\"" )
@ruby_opts.unshift( "-w" ) if @warning
ruby @ruby_opts.join(" ") +
" \"#{run_code}\" " +
@ -133,15 +133,6 @@ module Rake
end
end
def fix # :nodoc:
case RUBY_VERSION
when '1.8.2'
find_file 'rake/ruby182_test_unit_fix'
else
nil
end || ''
end
def rake_loader # :nodoc:
find_file('rake/rake_test_loader') or
fail "unable to find rake test loader"

View file

@ -5,9 +5,10 @@ module Rake
module Win32
class << self
# True if running on a windows system.
def windows?
# assume other DOSish systems are extinct.
File::ALT_SEPARATOR == '\\'
if File::ALT_SEPARATOR == '\\' # assume other DOSish systems are extinct.
def windows?; true end
else
def windows?; false end
end
end
@ -29,6 +30,17 @@ module Rake
end
File.expand_path('Rake', win32_shared_path)
end
# Normalize a win32 path so that the slashes are all forward slashes.
def normalize(path)
path.tr('\\', '/')
end
end if windows?
end
if Win32.windows?
def standard_system_dir
Win32.win32_system_dir
end
end
end

View file

@ -0,0 +1,24 @@
require 'stringio'
# Mix-in for capturing standard output.
module CaptureStdout
def capture_stdout
s = StringIO.new
oldstdout = $stdout
$stdout = s
yield
s.string
ensure
$stdout = oldstdout
end
def capture_stderr
s = StringIO.new
oldstderr = $stderr
$stderr = s
yield
s.string
ensure
$stderr = oldstderr
end
end

View file

@ -0,0 +1,5 @@
if ARGV[0] != ARGV[1]
exit 1
else
exit 0
end

View file

@ -0,0 +1,5 @@
if ARGV[0] != ARGV[1]
exit 0
else
exit 1
end

View file

@ -0,0 +1,15 @@
# -*- ruby -*-
task :default => "play.app"
file "play.scpt" => "base" do |t|
cp t.prerequisites.first, t.name
end
rule ".app" => ".scpt" do |t|
cp t.source, t.name
end
file 'base' do
touch 'base'
end

View file

@ -0,0 +1,19 @@
#!/usr/bin/env ruby
if ENV['TESTTOPSCOPE']
puts "TOPSCOPE"
end
task :default do
puts "DEFAULT"
end
task :other => [:default] do
puts "OTHER"
end
task :task_scope do
if ENV['TESTTASKSCOPE']
puts "TASKSCOPE"
end
end

View file

@ -0,0 +1,22 @@
#
task :default => ["temp_main"]
file "temp_main" => [:all_apps] do touch "temp_main" end
task :all_apps => [:one, :two]
task :one => ["temp_one"]
task :two => ["temp_two"]
file "temp_one" do |t|
touch "temp_one"
end
file "temp_two" do |t|
touch "temp_two"
end
task :clean do
["temp_one", "temp_two", "temp_main"].each do |file|
rm_f file
end
end

View file

@ -0,0 +1,33 @@
#!/usr/bin/env ruby
N = 2
task :default => :run
BUILD_DIR = 'build'
task :clean do
rm_rf 'build'
rm_rf 'src'
end
task :run
TARGET_DIR = 'build/copies'
FileList['src/*'].each do |src|
directory TARGET_DIR
target = File.join TARGET_DIR, File.basename(src)
file target => [src, TARGET_DIR] do
cp src, target
# sleep 3 if src !~ /foo#{N-1}$/ # I'm commenting out this sleep, it doesn't seem to do anything.
end
task :run => target
end
task :prep => :clean do
mkdir_p 'src'
N.times do |n|
puts "DBG: Touching src/foo#{n}"
touch "src/foo#{n}"
end
end

View file

@ -0,0 +1,19 @@
# -*- ruby -*-
require 'rake/loaders/makefile'
task :default
task :other do
puts "OTHER"
end
file "dynamic_deps" do |t|
open(t.name, "w") do |f| f.puts "puts 'DYNAMIC'" end
end
import "dynamic_deps"
import "static_deps"
import "static_deps"
import "deps.mf"
puts "FIRST"

View file

@ -0,0 +1 @@
default: other

View file

@ -0,0 +1,17 @@
#!/usr/bin/env ruby
task :b
desc "A"
task :a
desc "B"
task :b
desc "A2"
task :a
task :c
desc "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
task :d

View file

@ -0,0 +1,57 @@
#!/usr/bin/env ruby
desc "copy"
task :copy do
puts "COPY"
end
namespace "nest" do
desc "nest copy"
task :copy do
puts "NEST COPY"
end
task :xx => :copy
end
anon_ns = namespace do
desc "anonymous copy task"
task :copy do
puts "ANON COPY"
end
end
desc "Top level task to run the anonymous version of copy"
task :anon => anon_ns[:copy]
namespace "very" do
namespace "nested" do
task "run" => "rake:copy"
end
end
namespace "a" do
desc "Run task in the 'a' namespace"
task "run" do
puts "IN A"
end
end
namespace "b" do
desc "Run task in the 'b' namespace"
task "run" => "a:run" do
puts "IN B"
end
end
namespace "file1" do
file "xyz.rb" do
puts "XYZ1"
end
end
namespace "file2" do
file "xyz.rb" do
puts "XYZ2"
end
end

View file

@ -0,0 +1,3 @@
task :default do
puts "TEST1"
end

View file

@ -0,0 +1,3 @@
task :default do
puts "OK"
end

14
test/rake/data/sample.mf Normal file
View file

@ -0,0 +1,14 @@
# Comments
a: a1 a2 a3 a4
b: b1 b2 b3 \
b4 b5 b6\
# Mid: Comment
b7
a : a5 a6 a7
c: c1
d: d1 d2 \
e f : e1 f1
g\ 0: g1 g\ 2 g\ 3 g4

View file

@ -0,0 +1,8 @@
#!/usr/bin/env ruby
task :exit5 do
exit(5)
end
task :normal do
end

View file

@ -0,0 +1 @@
# Empty Rakefile for Unit Test

30
test/rake/filecreation.rb Normal file
View file

@ -0,0 +1,30 @@
module FileCreation
OLDFILE = "testdata/old"
NEWFILE = "testdata/new"
def create_timed_files(oldfile, *newfiles)
return if File.exist?(oldfile) && newfiles.all? { |newfile| File.exist?(newfile) }
old_time = create_file(oldfile)
newfiles.each do |newfile|
while create_file(newfile) <= old_time
sleep(0.1)
File.delete(newfile) rescue nil
end
end
end
def create_dir(dirname)
FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
File.stat(dirname).mtime
end
def create_file(name)
create_dir(File.dirname(name))
FileUtils.touch(name) unless File.exist?(name)
File.stat(name).mtime
end
def delete_file(name)
File.delete(name) rescue nil
end
end

View file

@ -0,0 +1,30 @@
module InEnvironment
private
# Create an environment for a test. At the completion of the yielded
# block, the environment is restored to its original conditions.
def in_environment(settings)
original_settings = set_env(settings)
yield
ensure
set_env(original_settings) if original_settings
end
# Set the environment according to the settings hash.
def set_env(settings) # :nodoc:
result = {}
settings.each do |k, v|
result[k] = ENV[k]
if k == 'PWD'
result[k] = Dir.pwd
Dir.chdir(v)
elsif v.nil?
ENV.delete(k)
else
ENV[k] = v
end
end
result
end
end

View file

@ -0,0 +1,9 @@
# Common setup for all test files.
# require 'flexmock/test_unit'
module TestMethods
def assert_exception(ex, msg=nil, &block)
assert_raise(ex, msg, &block)
end
end

3
test/rake/reqfile.rb Normal file
View file

@ -0,0 +1,3 @@
# For --require testing
TESTING_REQUIRE << 1

3
test/rake/reqfile2.rb Normal file
View file

@ -0,0 +1,3 @@
# For --require testing
TESTING_REQUIRE << 2

3
test/rake/reqfile3.rb Normal file
View file

@ -0,0 +1,3 @@
# For --require testing
TESTING_REQUIRE << 3

3
test/rake/shellcommand.rb Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env ruby
exit((ARGV[0] || "0").to_i)

687
test/rake/test_application.rb Executable file
View file

@ -0,0 +1,687 @@
require 'test/unit'
require 'rake'
require_relative 'capture_stdout'
require_relative 'in_environment'
TESTING_REQUIRE = [ ]
######################################################################
class TestApplication < Test::Unit::TestCase
include CaptureStdout
include InEnvironment
BASEDIR = File.dirname(__FILE__)
def defmock(*names, &block)
class << (@mock ||= Object.new); self; end.class_eval do
names.each do |name|
define_method(name, block)
end
end
@mock
end
def setup
@app = Rake::Application.new
@app.options.rakelib = []
end
def test_constant_warning
err = capture_stderr do @app.instance_eval { const_warning("Task") } end
assert_match(/warning/i, err)
assert_match(/deprecated/i, err)
assert_match(/Task/i, err)
end
def test_display_tasks
@app.options.show_task_pattern = //
@app.last_description = "COMMENT"
@app.define_task(Rake::Task, "t")
out = capture_stdout do @app.instance_eval { display_tasks_and_comments } end
assert_match(/^rake t/, out)
assert_match(/# COMMENT/, out)
end
def test_display_tasks_with_long_comments
in_environment('RAKE_COLUMNS' => '80') do
@app.options.show_task_pattern = //
@app.last_description = "1234567890" * 8
@app.define_task(Rake::Task, "t")
out = capture_stdout do @app.instance_eval { display_tasks_and_comments } end
assert_match(/^rake t/, out)
assert_match(/# 12345678901234567890123456789012345678901234567890123456789012345\.\.\./, out)
end
end
def test_display_tasks_with_task_name_wider_than_tty_display
in_environment('RAKE_COLUMNS' => '80') do
@app.options.show_task_pattern = //
description = "something short"
task_name = "task name" * 80
@app.last_description = "something short"
@app.define_task(Rake::Task, task_name )
out = capture_stdout do @app.instance_eval { display_tasks_and_comments } end
# Ensure the entire task name is output and we end up showing no description
assert_match(/rake #{task_name} # .../, out)
end
end
def test_display_tasks_with_very_long_task_name_to_a_non_tty_shows_name_and_comment
@app.options.show_task_pattern = //
@app.tty_output = false
description = "something short"
task_name = "task name" * 80
@app.last_description = "something short"
@app.define_task(Rake::Task, task_name )
out = capture_stdout do @app.instance_eval { display_tasks_and_comments } end
# Ensure the entire task name is output and we end up showing no description
assert_match(/rake #{task_name} # #{description}/, out)
end
def test_display_tasks_with_long_comments_to_a_non_tty_shows_entire_comment
@app.options.show_task_pattern = //
@app.tty_output = false
@app.last_description = "1234567890" * 8
@app.define_task(Rake::Task, "t")
out = capture_stdout do @app.instance_eval { display_tasks_and_comments } end
assert_match(/^rake t/, out)
assert_match(/# #{@app.last_description}/, out)
end
def test_display_tasks_with_long_comments_to_a_non_tty_with_columns_set_truncates_comments
in_environment("RAKE_COLUMNS" => '80') do
@app.options.show_task_pattern = //
@app.tty_output = false
@app.last_description = "1234567890" * 8
@app.define_task(Rake::Task, "t")
out = capture_stdout do @app.instance_eval { display_tasks_and_comments } end
assert_match(/^rake t/, out)
assert_match(/# 12345678901234567890123456789012345678901234567890123456789012345\.\.\./, out)
end
end
def test_display_tasks_with_full_descriptions
@app.options.show_task_pattern = //
@app.options.full_description = true
@app.last_description = "COMMENT"
@app.define_task(Rake::Task, "t")
out = capture_stdout do @app.instance_eval { display_tasks_and_comments } end
assert_match(/^rake t$/, out)
assert_match(/^ {4}COMMENT$/, out)
end
def test_finding_rakefile
in_environment("PWD" => File.join(BASEDIR, "data/unittest")) do
assert_match(/Rakefile/i, @app.instance_eval { have_rakefile })
end
end
def test_not_finding_rakefile
@app.instance_eval { @rakefiles = ['NEVER_FOUND'] }
assert( ! @app.instance_eval do have_rakefile end )
assert_nil @app.rakefile
end
def test_load_rakefile
in_environment("PWD" => File.join(BASEDIR, "data/unittest")) do
@app.instance_eval do
handle_options
options.silent = true
load_rakefile
end
assert_equal "rakefile", @app.rakefile.downcase
assert_match(%r(unittest$), Dir.pwd)
end
end
def test_load_rakefile_from_subdir
in_environment("PWD" => File.join(BASEDIR, "data/unittest/subdir")) do
@app.instance_eval do
handle_options
options.silent = true
load_rakefile
end
assert_equal "rakefile", @app.rakefile.downcase
assert_match(%r(unittest$), Dir.pwd)
end
end
def test_load_rakefile_not_found
in_environment("PWD" => "/", "RAKE_SYSTEM" => 'not_exist') do
@app.instance_eval do
handle_options
options.silent = true
end
ex = assert_raise(RuntimeError) do
@app.instance_eval do raw_load_rakefile end
end
assert_match(/no rakefile found/i, ex.message)
end
end
def test_load_from_system_rakefile
system_dir = File.expand_path('../data/default', __FILE__)
in_environment('RAKE_SYSTEM' => system_dir) do
@app.options.rakelib = []
@app.instance_eval do
handle_options
options.silent = true
options.load_system = true
options.rakelib = []
load_rakefile
end
assert_equal system_dir, @app.system_dir
assert_nil @app.rakefile
end
end
def test_windows
assert ! (@app.windows? && @app.unix?)
end
def test_loading_imports
args = []
mock = defmock(:load) {|*a| args << a}
@app.instance_eval do
add_loader("dummy", mock)
add_import("x.dummy")
load_imports
end
assert_equal([["x.dummy"]], args)
end
def test_building_imported_files_on_demand
args = []
callback = false
mock = defmock(:load) {|*a| args << a}
@app.instance_eval do
intern(Rake::Task, "x.dummy").enhance do callback = true end
add_loader("dummy", mock)
add_import("x.dummy")
load_imports
end
assert_equal([["x.dummy"]], args)
assert(callback)
end
def test_handle_options_should_strip_options_from_ARGV
assert !@app.options.trace
valid_option = '--trace'
ARGV.clear
ARGV << valid_option
@app.handle_options
assert !ARGV.include?(valid_option)
assert @app.options.trace
end
def test_good_run
ran = false
ARGV.clear
ARGV << '--rakelib=""'
@app.options.silent = true
@app.instance_eval do
intern(Rake::Task, "default").enhance { ran = true }
end
in_environment("PWD" => File.join(BASEDIR, "data/default")) do
@app.run
end
assert ran
end
def test_display_task_run
ran = false
ARGV.clear
ARGV << '-f' << '-s' << '--tasks' << '--rakelib=""'
@app.last_description = "COMMENT"
@app.define_task(Rake::Task, "default")
out = capture_stdout { @app.run }
assert @app.options.show_tasks
assert ! ran
assert_match(/rake default/, out)
assert_match(/# COMMENT/, out)
end
def test_display_prereqs
ran = false
ARGV.clear
ARGV << '-f' << '-s' << '--prereqs' << '--rakelib=""'
@app.last_description = "COMMENT"
t = @app.define_task(Rake::Task, "default")
t.enhance([:a, :b])
@app.define_task(Rake::Task, "a")
@app.define_task(Rake::Task, "b")
out = capture_stdout { @app.run }
assert @app.options.show_prereqs
assert ! ran
assert_match(/rake a$/, out)
assert_match(/rake b$/, out)
assert_match(/rake default\n( *(a|b)\n){2}/m, out)
end
def test_bad_run
@app.intern(Rake::Task, "default").enhance { fail }
ARGV.clear
ARGV << '-f' << '-s' << '--rakelib=""'
assert_raise(SystemExit) {
err = capture_stderr { @app.run }
assert_match(/see full trace/, err)
}
ensure
ARGV.clear
end
def test_bad_run_with_trace
@app.intern(Rake::Task, "default").enhance { fail }
ARGV.clear
ARGV << '-f' << '-s' << '-t'
assert_raise(SystemExit) {
err = capture_stderr { capture_stdout { @app.run } }
assert_no_match(/see full trace/, err)
}
ensure
ARGV.clear
end
def test_run_with_bad_options
@app.intern(Rake::Task, "default").enhance { fail }
ARGV.clear
ARGV << '-f' << '-s' << '--xyzzy'
assert_raise(SystemExit) {
err = capture_stderr { capture_stdout { @app.run } }
}
ensure
ARGV.clear
end
end
######################################################################
class TestApplicationOptions < Test::Unit::TestCase
include CaptureStdout
def setup
clear_argv
RakeFileUtils.verbose_flag = false
RakeFileUtils.nowrite_flag = false
TESTING_REQUIRE.clear
end
def teardown
clear_argv
RakeFileUtils.verbose_flag = false
RakeFileUtils.nowrite_flag = false
end
def clear_argv
while ! ARGV.empty?
ARGV.pop
end
end
def test_default_options
opts = command_line
assert_nil opts.classic_namespace
assert_nil opts.dryrun
assert_nil opts.full_description
assert_nil opts.ignore_system
assert_nil opts.load_system
assert_nil opts.nosearch
assert_equal ['rakelib'], opts.rakelib
assert_nil opts.show_prereqs
assert_nil opts.show_task_pattern
assert_nil opts.show_tasks
assert_nil opts.silent
assert_nil opts.trace
assert_equal ['rakelib'], opts.rakelib
assert ! RakeFileUtils.verbose_flag
assert ! RakeFileUtils.nowrite_flag
end
def test_dry_run
flags('--dry-run', '-n') do |opts|
assert opts.dryrun
assert opts.trace
assert RakeFileUtils.verbose_flag
assert RakeFileUtils.nowrite_flag
end
end
def test_describe
flags('--describe') do |opts|
assert opts.full_description
assert opts.show_tasks
assert_equal(//.to_s, opts.show_task_pattern.to_s)
end
end
def test_describe_with_pattern
flags('--describe=X') do |opts|
assert opts.full_description
assert opts.show_tasks
assert_equal(/X/.to_s, opts.show_task_pattern.to_s)
end
end
def test_execute
$xyzzy = 0
flags('--execute=$xyzzy=1', '-e $xyzzy=1') do |opts|
assert_equal 1, $xyzzy
assert_equal :exit, @exit
$xyzzy = 0
end
end
def test_execute_and_continue
$xyzzy = 0
flags('--execute-continue=$xyzzy=1', '-E $xyzzy=1') do |opts|
assert_equal 1, $xyzzy
assert_not_equal :exit, @exit
$xyzzy = 0
end
end
def test_execute_and_print
$xyzzy = 0
flags('--execute-print=$xyzzy="pugh"', '-p $xyzzy="pugh"') do |opts|
assert_equal 'pugh', $xyzzy
assert_equal :exit, @exit
assert_match(/^pugh$/, @out)
$xyzzy = 0
end
end
def test_help
flags('--help', '-H', '-h') do |opts|
assert_match(/\Arake/, @out)
assert_match(/\boptions\b/, @out)
assert_match(/\btargets\b/, @out)
assert_equal :exit, @exit
assert_equal :exit, @exit
end
end
def test_libdir
flags(['--libdir', 'xx'], ['-I', 'xx'], ['-Ixx']) do |opts|
$:.include?('xx')
end
ensure
$:.delete('xx')
end
def test_rakefile
flags(['--rakefile', 'RF'], ['--rakefile=RF'], ['-f', 'RF'], ['-fRF']) do |opts|
assert_equal ['RF'], @app.instance_eval { @rakefiles }
end
end
def test_rakelib
flags(['--rakelibdir', 'A:B:C'], ['--rakelibdir=A:B:C'], ['-R', 'A:B:C'], ['-RA:B:C']) do |opts|
assert_equal ['A', 'B', 'C'], opts.rakelib
end
end
def test_require
flags(['--require', File.expand_path('../reqfile', __FILE__)],
"-r#{File.expand_path('../reqfile2', __FILE__)}",
"-r#{File.expand_path('../reqfile3', __FILE__)}") do |opts|
end
assert TESTING_REQUIRE.include?(1)
assert TESTING_REQUIRE.include?(2)
assert TESTING_REQUIRE.include?(3)
assert_equal 3, TESTING_REQUIRE.size
end
def test_missing_require
ex = assert_raise(LoadError) do
flags(['--require', File.expand_path('../missing', __FILE__)]) do |opts|
end
end
assert_match(/no such file/, ex.message)
assert_match(/#{File.basename(File.dirname(__FILE__))}\/missing/, ex.message)
end
def test_prereqs
flags('--prereqs', '-P') do |opts|
assert opts.show_prereqs
end
end
def test_quiet
flags('--quiet', '-q') do |opts|
assert ! RakeFileUtils.verbose_flag
assert ! opts.silent
end
end
def test_no_search
flags('--nosearch', '--no-search', '-N') do |opts|
assert opts.nosearch
end
end
def test_silent
flags('--silent', '-s') do |opts|
assert ! RakeFileUtils.verbose_flag
assert opts.silent
end
end
def test_system
flags('--system', '-g') do |opts|
assert opts.load_system
end
end
def test_no_system
flags('--no-system', '-G') do |opts|
assert opts.ignore_system
end
end
def test_trace
flags('--trace', '-t') do |opts|
assert opts.trace
assert RakeFileUtils.verbose_flag
assert ! RakeFileUtils.nowrite_flag
end
end
def test_trace_rules
flags('--rules') do |opts|
assert opts.trace_rules
end
end
def test_tasks
flags('--tasks', '-T') do |opts|
assert opts.show_tasks
assert_equal(//.to_s, opts.show_task_pattern.to_s)
end
flags(['--tasks', 'xyz'], ['-Txyz']) do |opts|
assert opts.show_tasks
assert_equal(/xyz/, opts.show_task_pattern)
end
end
def test_verbose
flags('--verbose', '-V') do |opts|
assert RakeFileUtils.verbose_flag
assert ! opts.silent
end
end
def test_version
flags('--version', '-V') do |opts|
assert_match(/\bversion\b/, @out)
assert_match(/\b#{RAKEVERSION}\b/, @out)
assert_equal :exit, @exit
end
end
def test_classic_namespace
flags(['--classic-namespace'], ['-C', '-T', '-P', '-n', '-s', '-t']) do |opts|
assert opts.classic_namespace
assert_equal opts.show_tasks, $show_tasks
assert_equal opts.show_prereqs, $show_prereqs
assert_equal opts.trace, $trace
assert_equal opts.dryrun, $dryrun
assert_equal opts.silent, $silent
end
end
def test_bad_option
capture_stderr do
ex = assert_raise(OptionParser::InvalidOption) do
flags('--bad-option')
end
if ex.message =~ /^While/ # Ruby 1.9 error message
assert_match(/while parsing/i, ex.message)
else # Ruby 1.8 error message
assert_match(/(invalid|unrecognized) option/i, ex.message)
assert_match(/--bad-option/, ex.message)
end
end
end
def test_task_collection
command_line("a", "b")
assert_equal ["a", "b"], @tasks.sort
end
def test_default_task_collection
command_line()
assert_equal ["default"], @tasks
end
def test_environment_definition
ENV.delete('TESTKEY')
command_line("a", "TESTKEY=12")
assert_equal ["a"], @tasks.sort
assert '12', ENV['TESTKEY']
end
private
def flags(*sets)
sets.each do |set|
ARGV.clear
@out = capture_stdout {
@exit = catch(:system_exit) { opts = command_line(*set) }
}
yield(@app.options) if block_given?
end
end
def command_line(*options)
options.each do |opt| ARGV << opt end
@app = Rake::Application.new
def @app.exit(*args)
throw :system_exit, :exit
end
@app.instance_eval do
handle_options
collect_tasks
end
@tasks = @app.top_level_tasks
@app.options
end
end
class TestTaskArgumentParsing < Test::Unit::TestCase
def setup
@app = Rake::Application.new
end
def test_name_only
name, args = @app.parse_task_string("name")
assert_equal "name", name
assert_equal [], args
end
def test_empty_args
name, args = @app.parse_task_string("name[]")
assert_equal "name", name
assert_equal [], args
end
def test_one_argument
name, args = @app.parse_task_string("name[one]")
assert_equal "name", name
assert_equal ["one"], args
end
def test_two_arguments
name, args = @app.parse_task_string("name[one,two]")
assert_equal "name", name
assert_equal ["one", "two"], args
end
def test_can_handle_spaces_between_args
name, args = @app.parse_task_string("name[one, two,\tthree , \tfour]")
assert_equal "name", name
assert_equal ["one", "two", "three", "four"], args
end
def test_keeps_embedded_spaces
name, args = @app.parse_task_string("name[a one ana, two]")
assert_equal "name", name
assert_equal ["a one ana", "two"], args
end
end
class TestTaskArgumentParsing < Test::Unit::TestCase
include InEnvironment
def test_terminal_width_using_env
app = Rake::Application.new
in_environment('RAKE_COLUMNS' => '1234') do
assert_equal 1234, app.terminal_width
end
end
def test_terminal_width_using_stty
app = Rake::Application.new
def app.unix?() true end
def app.dynamic_width_stty() 1235 end
def app.dynamic_width_tput() 0 end
in_environment('RAKE_COLUMNS' => nil) do
assert_equal 1235, app.terminal_width
end
end
def test_terminal_width_using_tput
app = Rake::Application.new
def app.unix?() true end
def app.dynamic_width_stty() 0 end
def app.dynamic_width_tput() 1236 end
in_environment('RAKE_COLUMNS' => nil) do
assert_equal 1236, app.terminal_width
end
end
def test_terminal_width_using_hardcoded_80
app = Rake::Application.new
def app.unix?() false end
in_environment('RAKE_COLUMNS' => nil) do
assert_equal 80, app.terminal_width
end
end
def test_terminal_width_with_failure
app = Rake::Application.new
called = false
class << app; self; end.class_eval do
define_method(:unix?) {|*a|
called = a
raise RuntimeError
}
end
in_environment('RAKE_COLUMNS' => nil) do
assert_equal 80, app.terminal_width
end
assert_equal([], called)
end
end

12
test/rake/test_clean.rb Normal file
View file

@ -0,0 +1,12 @@
require 'test/unit'
require 'rake/clean'
class TestClean < Test::Unit::TestCase
include Rake
def test_clean
assert Task['clean'], "Should define clean"
assert Task['clobber'], "Should define clobber"
assert Task['clobber'].prerequisites.include?("clean"),
"Clobber should require clean"
end
end

View file

@ -0,0 +1,81 @@
require 'test/unit'
require 'fileutils'
require 'rake'
require_relative 'filecreation'
######################################################################
class TestDefinitions < Test::Unit::TestCase
include Rake
EXISTINGFILE = "testdata/existing"
def setup
Task.clear
end
def test_task
done = false
task :one => [:two] do done = true end
task :two
task :three => [:one, :two]
check_tasks(:one, :two, :three)
assert done, "Should be done"
end
def test_file_task
done = false
file "testdata/one" => "testdata/two" do done = true end
file "testdata/two"
file "testdata/three" => ["testdata/one", "testdata/two"]
check_tasks("testdata/one", "testdata/two", "testdata/three")
assert done, "Should be done"
end
def check_tasks(n1, n2, n3)
t = Task[n1]
assert Task === t, "Should be a Task"
assert_equal n1.to_s, t.name
assert_equal [n2.to_s], t.prerequisites.collect{|n| n.to_s}
t.invoke
t2 = Task[n2]
assert_equal FileList[], t2.prerequisites
t3 = Task[n3]
assert_equal [n1.to_s, n2.to_s], t3.prerequisites.collect{|n|n.to_s}
end
def test_incremental_definitions
runs = []
task :t1 => [:t2] do runs << "A"; 4321 end
task :t1 => [:t3] do runs << "B"; 1234 end
task :t1 => [:t3]
task :t2
task :t3
Task[:t1].invoke
assert_equal ["A", "B"], runs
assert_equal ["t2", "t3"], Task[:t1].prerequisites
end
def test_missing_dependencies
task :x => ["testdata/missing"]
assert_raise(RuntimeError) { Task[:x].invoke }
end
def test_implicit_file_dependencies
runs = []
create_existing_file
task :y => [EXISTINGFILE] do |t| runs << t.name end
Task[:y].invoke
assert_equal runs, ['y']
end
private # ----------------------------------------------------------
def create_existing_file
Dir.mkdir File.dirname(EXISTINGFILE) unless
File.exist?(File.dirname(EXISTINGFILE))
open(EXISTINGFILE, "w") do |f| f.puts "HI" end unless
File.exist?(EXISTINGFILE)
end
end

View file

@ -0,0 +1,33 @@
require 'test/unit'
require 'rake'
class TestEarlyTime < Test::Unit::TestCase
def test_create
early = Rake::EarlyTime.instance
time = Time.mktime(1970, 1, 1, 0, 0, 0)
assert early <= Time.now
assert early < Time.now
assert early != Time.now
assert Time.now > early
assert Time.now >= early
assert Time.now != early
end
def test_equality
early = Rake::EarlyTime.instance
assert_equal early, early, "two early times should be equal"
end
def test_original_time_compare_is_not_messed_up
t1 = Time.mktime(1970, 1, 1, 0, 0, 0)
t2 = Time.now
assert t1 < t2
assert t2 > t1
assert t1 == t1
assert t2 == t2
end
def test_to_s
assert_equal "<EARLY TIME>", Rake::EARLY.to_s
end
end

View file

@ -0,0 +1,61 @@
require 'test/unit'
require 'rake'
require 'stringio'
######################################################################
class TestExtension < Test::Unit::TestCase
module Redirect
def error_redirect
old_err = $stderr
result = StringIO.new
$stderr = result
yield
result
ensure
$stderr = old_err
end
end
class Sample
extend Redirect
def duplicate_method
:original
end
OK_ERRS = error_redirect do
rake_extension("a") do
def ok_method
end
end
end
DUP_ERRS = error_redirect do
rake_extension("duplicate_method") do
def duplicate_method
:override
end
end
end
end
def test_methods_actually_exist
sample = Sample.new
sample.ok_method
sample.duplicate_method
end
def test_no_warning_when_defining_ok_method
assert_equal "", Sample::OK_ERRS.string
end
def test_extension_complains_when_a_method_that_is_present
assert_match(/warning:/i, Sample::DUP_ERRS.string)
assert_match(/already exists/i, Sample::DUP_ERRS.string)
assert_match(/duplicate_method/i, Sample::DUP_ERRS.string)
assert_equal :original, Sample.new.duplicate_method
end
end

View file

@ -0,0 +1,60 @@
require 'test/unit'
require 'fileutils'
require 'rake'
require_relative 'filecreation'
######################################################################
class TestFileCreationTask < Test::Unit::TestCase
include Rake
include FileCreation
DUMMY_DIR = 'testdata/dummy_dir'
def setup
Task.clear
end
def teardown
FileUtils.rm_rf DUMMY_DIR
end
def test_file_needed
create_dir DUMMY_DIR
fc_task = Task[DUMMY_DIR]
assert_equal DUMMY_DIR, fc_task.name
FileUtils.rm_rf fc_task.name
assert fc_task.needed?, "file should be needed"
FileUtils.mkdir fc_task.name
assert_equal nil, fc_task.prerequisites.collect{|n| Task[n].timestamp}.max
assert ! fc_task.needed?, "file should not be needed"
end
def test_directory
directory DUMMY_DIR
fc_task = Task[DUMMY_DIR]
assert_equal DUMMY_DIR, fc_task.name
assert FileCreationTask === fc_task
end
def test_no_retriggers_on_filecreate_task
create_timed_files(OLDFILE, NEWFILE)
t1 = Rake.application.intern(FileCreationTask, OLDFILE).enhance([NEWFILE])
t2 = Rake.application.intern(FileCreationTask, NEWFILE)
assert ! t2.needed?, "Should not need to build new file"
assert ! t1.needed?, "Should not need to rebuild old file because of new"
end
def test_no_retriggers_on_file_task
create_timed_files(OLDFILE, NEWFILE)
t1 = Rake.application.intern(FileCreationTask, OLDFILE).enhance([NEWFILE])
t2 = Rake.application.intern(FileCreationTask, NEWFILE)
assert ! t2.needed?, "Should not need to build new file"
assert ! t1.needed?, "Should not need to rebuild old file because of new"
end
def test_very_early_timestamp
t1 = Rake.application.intern(FileCreationTask, OLDFILE)
assert t1.timestamp < Time.now
assert t1.timestamp < Time.now - 1000000
end
end

139
test/rake/test_file_task.rb Normal file
View file

@ -0,0 +1,139 @@
require 'test/unit'
require 'fileutils'
require 'rake'
require_relative 'filecreation'
######################################################################
class TestFileTask < Test::Unit::TestCase
include Rake
include FileCreation
def setup
Task.clear
@runs = Array.new
FileUtils.rm_f NEWFILE
FileUtils.rm_f OLDFILE
end
def test_file_need
name = "testdata/dummy"
file name
ftask = Task[name]
assert_equal name.to_s, ftask.name
File.delete(ftask.name) rescue nil
assert ftask.needed?, "file should be needed"
open(ftask.name, "w") { |f| f.puts "HI" }
assert_equal nil, ftask.prerequisites.collect{|n| Task[n].timestamp}.max
assert ! ftask.needed?, "file should not be needed"
File.delete(ftask.name) rescue nil
end
def test_file_times_new_depends_on_old
create_timed_files(OLDFILE, NEWFILE)
t1 = Rake.application.intern(FileTask, NEWFILE).enhance([OLDFILE])
t2 = Rake.application.intern(FileTask, OLDFILE)
assert ! t2.needed?, "Should not need to build old file"
assert ! t1.needed?, "Should not need to rebuild new file because of old"
end
def test_file_times_old_depends_on_new
create_timed_files(OLDFILE, NEWFILE)
t1 = Rake.application.intern(FileTask,OLDFILE).enhance([NEWFILE])
t2 = Rake.application.intern(FileTask, NEWFILE)
assert ! t2.needed?, "Should not need to build new file"
preq_stamp = t1.prerequisites.collect{|t| Task[t].timestamp}.max
assert_equal t2.timestamp, preq_stamp
assert t1.timestamp < preq_stamp, "T1 should be older"
assert t1.needed?, "Should need to rebuild old file because of new"
end
def test_file_depends_on_task_depend_on_file
create_timed_files(OLDFILE, NEWFILE)
file NEWFILE => [:obj] do |t| @runs << t.name end
task :obj => [OLDFILE] do |t| @runs << t.name end
file OLDFILE do |t| @runs << t.name end
Task[:obj].invoke
Task[NEWFILE].invoke
assert ! @runs.include?(NEWFILE)
end
def test_existing_file_depends_on_non_existing_file
create_file(OLDFILE)
delete_file(NEWFILE)
file NEWFILE
file OLDFILE => NEWFILE
assert_nothing_raised do Task[OLDFILE].invoke end
end
# I have currently disabled this test. I'm not convinced that
# deleting the file target on failure is always the proper thing to
# do. I'm willing to hear input on this topic.
def ztest_file_deletes_on_failure
task :obj
file NEWFILE => [:obj] do |t|
FileUtils.touch NEWFILE
fail "Ooops"
end
assert Task[NEWFILE]
begin
Task[NEWFILE].invoke
rescue Exception
end
assert( ! File.exist?(NEWFILE), "NEWFILE should be deleted")
end
end
######################################################################
class TestDirectoryTask < Test::Unit::TestCase
include Rake
def setup
rm_rf "testdata", :verbose=>false
end
def teardown
rm_rf "testdata", :verbose=>false
end
def test_directory
desc "DESC"
directory "testdata/a/b/c"
assert_equal FileCreationTask, Task["testdata"].class
assert_equal FileCreationTask, Task["testdata/a"].class
assert_equal FileCreationTask, Task["testdata/a/b/c"].class
assert_nil Task["testdata"].comment
assert_equal "DESC", Task["testdata/a/b/c"].comment
assert_nil Task["testdata/a/b"].comment
verbose(false) {
Task['testdata/a/b'].invoke
}
assert File.exist?("testdata/a/b")
assert ! File.exist?("testdata/a/b/c")
end
if Rake::Win32.windows?
def test_directory_win32
desc "WIN32 DESC"
FileUtils.mkdir_p("testdata")
Dir.chdir("testdata") do
directory 'c:/testdata/a/b/c'
assert_equal FileCreationTask, Task['c:/testdata'].class
assert_equal FileCreationTask, Task['c:/testdata/a'].class
assert_equal FileCreationTask, Task['c:/testdata/a/b/c'].class
assert_nil Task['c:/testdata'].comment
assert_equal "WIN32 DESC", Task['c:/testdata/a/b/c'].comment
assert_nil Task['c:/testdata/a/b'].comment
verbose(false) {
Task['c:/testdata/a/b'].invoke
}
assert File.exist?('c:/testdata/a/b')
assert ! File.exist?('c:/testdata/a/b/c')
end
end
end
end

625
test/rake/test_filelist.rb Normal file
View file

@ -0,0 +1,625 @@
require 'test/unit'
require 'tmpdir'
require 'rake'
require_relative 'capture_stdout'
class TestFileList < Test::Unit::TestCase
FileList = Rake::FileList
include CaptureStdout
def setup
@oldwd = Dir.pwd
@tmpwd = Dir.mktmpdir
Dir.chdir(@tmpwd)
create_test_data
end
def teardown
# FileList.select_default_ignore_patterns
FileUtils.rm_rf("testdata")
Dir.chdir(@oldwd)
FileUtils.rm_rf(@tmpwd)
end
def test_delgating_methods_do_not_include_to_a_or_to_ary
assert ! FileList::DELEGATING_METHODS.include?("to_a"), "should not include to_a"
assert ! FileList::DELEGATING_METHODS.include?(:to_a), "should not include to_a"
assert ! FileList::DELEGATING_METHODS.include?("to_ary"), "should not include to_ary"
assert ! FileList::DELEGATING_METHODS.include?(:to_ary), "should not include to_ary"
end
def test_create
fl = FileList.new
assert_equal 0, fl.size
end
def test_create_with_args
fl = FileList.new("testdata/*.c", "x")
assert_equal ["testdata/abc.c", "testdata/x.c", "testdata/xyz.c", "x"].sort,
fl.sort
end
def test_create_with_block
fl = FileList.new { |f| f.include("x") }
assert_equal ["x"], fl.resolve
end
def test_create_with_brackets
fl = FileList["testdata/*.c", "x"]
assert_equal ["testdata/abc.c", "testdata/x.c", "testdata/xyz.c", "x"].sort,
fl.sort
end
def test_create_with_brackets_and_filelist
fl = FileList[FileList["testdata/*.c", "x"]]
assert_equal ["testdata/abc.c", "testdata/x.c", "testdata/xyz.c", "x"].sort,
fl.sort
end
def test_include_with_another_array
fl = FileList.new.include(["x", "y", "z"])
assert_equal ["x", "y", "z"].sort, fl.sort
end
def test_include_with_another_filelist
fl = FileList.new.include(FileList["testdata/*.c", "x"])
assert_equal ["testdata/abc.c", "testdata/x.c", "testdata/xyz.c", "x"].sort,
fl.sort
end
def test_append
fl = FileList.new
fl << "a.rb" << "b.rb"
assert_equal ['a.rb', 'b.rb'], fl
end
def test_add_many
fl = FileList.new
fl.include %w(a d c)
fl.include('x', 'y')
assert_equal ['a', 'd', 'c', 'x', 'y'], fl
assert_equal ['a', 'd', 'c', 'x', 'y'], fl.resolve
end
def test_add_return
f = FileList.new
g = f << "x"
assert_equal f.object_id, g.object_id
h = f.include("y")
assert_equal f.object_id, h.object_id
end
def test_match
fl = FileList.new
fl.include(File.expand_path('../test*.rb', __FILE__))
assert fl.include?(__FILE__)
assert fl.size > 3
fl.each { |fn| assert_match(/\.rb$/, fn) }
end
def test_add_matching
fl = FileList.new
fl << "a.java"
fl.include(File.dirname(__FILE__)+"/*.rb")
assert_equal "a.java", fl[0]
assert fl.size > 2
assert fl.include?(__FILE__)
end
def test_multiple_patterns
create_test_data
fl = FileList.new
fl.include('*.c', '*xist*')
assert_equal [], fl
fl.include('testdata/*.c', 'testdata/*xist*')
assert_equal [
'testdata/x.c', 'testdata/xyz.c', 'testdata/abc.c', 'testdata/existing'
].sort, fl.sort
end
def test_square_bracket_pattern
fl = FileList.new
fl.include("testdata/abc.[ch]")
assert fl.size == 2
assert fl.include?("testdata/abc.c")
assert fl.include?("testdata/abc.h")
end
def test_curly_bracket_pattern
fl = FileList.new
fl.include("testdata/abc.{c,h}")
assert fl.size == 2
assert fl.include?("testdata/abc.c")
assert fl.include?("testdata/abc.h")
end
def test_reject
fl = FileList.new
fl.include %w(testdata/x.c testdata/abc.c testdata/xyz.c testdata/existing)
fl.reject! { |fn| fn =~ %r{/x} }
assert_equal [
'testdata/abc.c', 'testdata/existing'
], fl
end
def test_exclude
fl = FileList['testdata/x.c', 'testdata/abc.c', 'testdata/xyz.c', 'testdata/existing']
fl.each { |fn| touch fn, :verbose => false }
x = fl.exclude(%r{/x.+\.})
assert_equal FileList, x.class
assert_equal %w(testdata/x.c testdata/abc.c testdata/existing), fl
assert_equal fl.object_id, x.object_id
fl.exclude('testdata/*.c')
assert_equal ['testdata/existing'], fl
fl.exclude('testdata/existing')
assert_equal [], fl
end
def test_excluding_via_block
fl = FileList['testdata/a.c', 'testdata/b.c', 'testdata/xyz.c']
fl.exclude { |fn| fn.pathmap('%n') == 'xyz' }
assert fl.exclude?("xyz.c"), "Should exclude xyz.c"
assert_equal ['testdata/a.c', 'testdata/b.c'], fl
end
def test_exclude_return_on_create
fl = FileList['testdata/*'].exclude(/.*\.[hcx]$/)
assert_equal ['testdata/existing', 'testdata/cfiles'].sort, fl.sort
assert_equal FileList, fl.class
end
def test_exclude_with_string_return_on_create
fl = FileList['testdata/*'].exclude('testdata/abc.c')
assert_equal %w(testdata/existing testdata/cfiles testdata/x.c testdata/abc.h testdata/abc.x testdata/xyz.c).sort, fl.sort
assert_equal FileList, fl.class
end
def test_default_exclude
fl = FileList.new
fl.clear_exclude
fl.include("**/*~", "**/*.bak", "**/core")
assert fl.member?("testdata/core"), "Should include core"
assert fl.member?("testdata/x.bak"), "Should include .bak files"
end
def test_unique
fl = FileList.new
fl << "x.c" << "a.c" << "b.rb" << "a.c"
assert_equal ['x.c', 'a.c', 'b.rb', 'a.c'], fl
fl.uniq!
assert_equal ['x.c', 'a.c', 'b.rb'], fl
end
def test_to_string
fl = FileList.new
fl << "a.java" << "b.java"
assert_equal "a.java b.java", fl.to_s
assert_equal "a.java b.java", "#{fl}"
end
def test_to_array
fl = FileList['a.java', 'b.java']
assert_equal ['a.java', 'b.java'], fl.to_a
assert_equal Array, fl.to_a.class
assert_equal ['a.java', 'b.java'], fl.to_ary
assert_equal Array, fl.to_ary.class
end
def test_to_s_pending
fl = FileList['testdata/abc.*']
result = fl.to_s
assert_match(%r{testdata/abc\.c}, result)
assert_match(%r{testdata/abc\.h}, result)
assert_match(%r{testdata/abc\.x}, result)
assert_match(%r{(testdata/abc\..\b ?){2}}, result)
end
def test_inspect_pending
fl = FileList['testdata/abc.*']
result = fl.inspect
assert_match(%r{"testdata/abc\.c"}, result)
assert_match(%r{"testdata/abc\.h"}, result)
assert_match(%r{"testdata/abc\.x"}, result)
assert_match(%r|^\[("testdata/abc\..", ){2}"testdata/abc\.."\]$|, result)
end
def test_sub
fl = FileList["testdata/*.c"]
f2 = fl.sub(/\.c$/, ".o")
assert_equal FileList, f2.class
assert_equal ["testdata/abc.o", "testdata/x.o", "testdata/xyz.o"].sort,
f2.sort
f3 = fl.gsub(/\.c$/, ".o")
assert_equal FileList, f3.class
assert_equal ["testdata/abc.o", "testdata/x.o", "testdata/xyz.o"].sort,
f3.sort
end
def test_claim_to_be_a_kind_of_array
fl = FileList['testdata/*.c']
assert fl.is_a?(Array)
assert fl.kind_of?(Array)
end
def test_claim_to_be_a_kind_of_filelist
fl = FileList['testdata/*.c']
assert fl.is_a?(FileList)
assert fl.kind_of?(FileList)
end
def test_claim_to_be_a_filelist_instance
fl = FileList['testdata/*.c']
assert fl.instance_of?(FileList)
end
def test_dont_claim_to_be_an_array_instance
fl = FileList['testdata/*.c']
assert ! fl.instance_of?(Array)
end
def test_sub!
f = "x/a.c"
fl = FileList[f, "x/b.c"]
res = fl.sub!(/\.c$/, ".o")
assert_equal ["x/a.o", "x/b.o"].sort, fl.sort
assert_equal "x/a.c", f
assert_equal fl.object_id, res.object_id
end
def test_sub_with_block
fl = FileList["src/org/onestepback/a.java", "src/org/onestepback/b.java"]
# The block version doesn't work the way I want it to ...
# f2 = fl.sub(%r{^src/(.*)\.java$}) { |x| "classes/" + $1 + ".class" }
f2 = fl.sub(%r{^src/(.*)\.java$}, "classes/\\1.class")
assert_equal [
"classes/org/onestepback/a.class",
"classes/org/onestepback/b.class"
].sort,
f2.sort
end
def test_string_ext
assert_equal "one.net", "one.two".ext("net")
assert_equal "one.net", "one.two".ext(".net")
assert_equal "one.net", "one".ext("net")
assert_equal "one.net", "one".ext(".net")
assert_equal "one.two.net", "one.two.c".ext(".net")
assert_equal "one/two.net", "one/two.c".ext(".net")
assert_equal "one.x/two.net", "one.x/two.c".ext(".net")
assert_equal "one.x/two.net", "one.x/two".ext(".net")
assert_equal ".onerc.net", ".onerc.dot".ext("net")
assert_equal ".onerc.net", ".onerc".ext("net")
assert_equal ".a/.onerc.net", ".a/.onerc".ext("net")
assert_equal "one", "one.two".ext('')
assert_equal "one", "one.two".ext
assert_equal ".one", ".one.two".ext
assert_equal ".one", ".one".ext
assert_equal ".", ".".ext("c")
assert_equal "..", "..".ext("c")
# These only need to work in windows
if Rake::Win32.windows?
assert_equal "one.x\\two.net", "one.x\\two.c".ext(".net")
assert_equal "one.x\\two.net", "one.x\\two".ext(".net")
end
end
def test_filelist_ext
assert_equal FileList['one.c', '.one.c'],
FileList['one.net', '.one'].ext('c')
end
def test_gsub
create_test_data
fl = FileList["testdata/*.c"]
f2 = fl.gsub(/a/, "A")
assert_equal ["testdAtA/Abc.c", "testdAtA/x.c", "testdAtA/xyz.c"].sort,
f2.sort
end
def test_gsub!
create_test_data
f = FileList["testdata/*.c"]
f.gsub!(/a/, "A")
assert_equal ["testdAtA/Abc.c", "testdAtA/x.c", "testdAtA/xyz.c"].sort,
f.sort
end
def test_egrep_with_output
files = FileList[File.expand_path('../test*.rb', __FILE__)]
the_line_number = __LINE__ + 1
out = capture_stdout do files.egrep(/PUGH/) end
assert_match(/:#{the_line_number}:/, out)
end
def test_egrep_with_block
files = FileList[File.expand_path('../test*.rb', __FILE__)]
found = false
the_line_number = __LINE__ + 1
files.egrep(/XYZZY/) do |fn, ln, line |
assert_equal __FILE__, fn
assert_equal the_line_number, ln
assert_match(/files\.egrep/, line)
found = true
end
assert found, "should have found a matching line"
end
def test_existing
fl = FileList['testdata/abc.c', 'testdata/notthere.c']
assert_equal ["testdata/abc.c"], fl.existing
assert fl.existing.is_a?(FileList)
end
def test_existing!
fl = FileList['testdata/abc.c', 'testdata/notthere.c']
result = fl.existing!
assert_equal ["testdata/abc.c"], fl
assert_equal fl.object_id, result.object_id
end
def test_ignore_special
f = FileList['testdata/*']
assert ! f.include?("testdata/CVS"), "Should not contain CVS"
assert ! f.include?("testdata/.svn"), "Should not contain .svn"
assert ! f.include?("testdata/.dummy"), "Should not contain dot files"
assert ! f.include?("testdata/x.bak"), "Should not contain .bak files"
assert ! f.include?("testdata/x~"), "Should not contain ~ files"
assert ! f.include?("testdata/core"), "Should not contain core files"
end
def test_clear_ignore_patterns
f = FileList['testdata/*', 'testdata/.svn']
f.clear_exclude
assert f.include?("testdata/abc.c")
assert f.include?("testdata/xyz.c")
assert f.include?("testdata/CVS")
assert f.include?("testdata/.svn")
assert f.include?("testdata/x.bak")
assert f.include?("testdata/x~")
end
def test_exclude_with_alternate_file_seps
fl = FileList.new
assert fl.exclude?("x/CVS/y")
assert fl.exclude?("x\\CVS\\y")
assert fl.exclude?("x/.svn/y")
assert fl.exclude?("x\\.svn\\y")
assert fl.exclude?("x/core")
assert fl.exclude?("x\\core")
end
def test_add_default_exclude_list
fl = FileList.new
fl.exclude(/~\d+$/)
assert fl.exclude?("x/CVS/y")
assert fl.exclude?("x\\CVS\\y")
assert fl.exclude?("x/.svn/y")
assert fl.exclude?("x\\.svn\\y")
assert fl.exclude?("x/core")
assert fl.exclude?("x\\core")
assert fl.exclude?("x/abc~1")
end
def test_basic_array_functions
f = FileList['b', 'c', 'a']
assert_equal 'b', f.first
assert_equal 'b', f[0]
assert_equal 'a', f.last
assert_equal 'a', f[2]
assert_equal 'a', f[-1]
assert_equal ['a', 'b', 'c'], f.sort
f.sort!
assert_equal ['a', 'b', 'c'], f
end
def test_flatten
assert_equal ['a', 'testdata/x.c', 'testdata/xyz.c', 'testdata/abc.c'].sort,
['a', FileList['testdata/*.c']].flatten.sort
end
def test_clone_and_dup
a = FileList['a', 'b', 'c']
c = a.clone
d = a.dup
a << 'd'
assert_equal ['a', 'b', 'c', 'd'], a
assert_equal ['a', 'b', 'c'], c
assert_equal ['a', 'b', 'c'], d
end
def test_dup_and_clone_replicate_taint
a = FileList['a', 'b', 'c']
a.taint
c = a.clone
d = a.dup
assert c.tainted?, "Clone should be tainted"
assert d.tainted?, "Dup should be tainted"
end
def test_duped_items_will_thaw
a = FileList['a', 'b', 'c']
a.freeze
d = a.dup
d << 'more'
assert_equal ['a', 'b', 'c', 'more'], d
end
def test_cloned_items_stay_frozen
a = FileList['a', 'b', 'c']
a.freeze
c = a.clone
assert_raise(TypeError, RuntimeError) do
c << 'more'
end
end
def test_array_comparisons
fl = FileList['b', 'b']
a = ['b', 'a']
b = ['b', 'b']
c = ['b', 'c']
assert_equal( 1, fl <=> a )
assert_equal( 0, fl <=> b )
assert_equal( -1, fl <=> c )
assert_equal( -1, a <=> fl )
assert_equal( 0, b <=> fl )
assert_equal( 1, c <=> fl )
end
def test_array_equality
a = FileList['a', 'b']
b = ['a', 'b']
assert a == b
assert b == a
# assert a.eql?(b)
# assert b.eql?(a)
assert ! a.equal?(b)
assert ! b.equal?(a)
end
def test_enumeration_methods
a = FileList['a', 'b']
b = a.collect { |it| it.upcase }
assert_equal ['A', 'B'], b
assert_equal FileList, b.class
b = a.map { |it| it.upcase }
assert_equal ['A', 'B'], b
assert_equal FileList, b.class
b = a.sort
assert_equal ['a', 'b'], b
assert_equal FileList, b.class
b = a.sort_by { |it| it }
assert_equal ['a', 'b'], b
assert_equal FileList, b.class
b = a.find_all { |it| it == 'b'}
assert_equal ['b'], b
assert_equal FileList, b.class
b = a.select { |it| it.size == 1 }
assert_equal ['a', 'b'], b
assert_equal FileList, b.class
b = a.reject { |it| it == 'b' }
assert_equal ['a'], b
assert_equal FileList, b.class
b = a.grep(/./)
assert_equal ['a', 'b'], b
assert_equal FileList, b.class
b = a.partition { |it| it == 'b' }
assert_equal [['b'], ['a']], b
assert_equal Array, b.class
assert_equal FileList, b[0].class
assert_equal FileList, b[1].class
b = a.zip(['x', 'y']).to_a
assert_equal [['a', 'x'], ['b', 'y']], b
assert_equal Array, b.class
assert_equal Array, b[0].class
assert_equal Array, b[1].class
end
def test_array_operators
a = ['a', 'b']
b = ['c', 'd']
f = FileList['x', 'y']
g = FileList['w', 'z']
r = f + g
assert_equal ['x', 'y', 'w', 'z'], r
assert_equal FileList, r.class
r = a + g
assert_equal ['a', 'b', 'w', 'z'], r
assert_equal Array, r.class
r = f + b
assert_equal ['x', 'y', 'c', 'd'], r
assert_equal FileList, r.class
r = FileList['w', 'x', 'y', 'z'] - f
assert_equal ['w', 'z'], r
assert_equal FileList, r.class
r = FileList['w', 'x', 'y', 'z'] & f
assert_equal ['x', 'y'], r
assert_equal FileList, r.class
r = f * 2
assert_equal ['x', 'y', 'x', 'y'], r
assert_equal FileList, r.class
r = f * ','
assert_equal 'x,y', r
assert_equal String, r.class
r = f | ['a', 'x']
assert_equal ['a', 'x', 'y'].sort, r.sort
assert_equal FileList, r.class
end
def test_other_array_returning_methods
f = FileList['a', nil, 'b']
r = f.compact
assert_equal ['a', 'b'], r
assert_equal FileList, r.class
f = FileList['a', 'b']
r = f.concat(['x', 'y'])
assert_equal ['a', 'b', 'x', 'y'], r
assert_equal FileList, r.class
f = FileList['a', ['b', 'c'], FileList['d', 'e']]
r = f.flatten
assert_equal ['a', 'b', 'c', 'd', 'e'], r
assert_equal FileList, r.class
f = FileList['a', 'b', 'a']
r = f.uniq
assert_equal ['a', 'b'], r
assert_equal FileList, r.class
f = FileList['a', 'b', 'c', 'd']
r = f.values_at(1,3)
assert_equal ['b', 'd'], r
assert_equal FileList, r.class
end
def test_file_utils_can_use_filelists
cfiles = FileList['testdata/*.c']
cp cfiles, @cdir, :verbose => false
assert File.exist?(File.join(@cdir, 'abc.c'))
assert File.exist?(File.join(@cdir, 'xyz.c'))
assert File.exist?(File.join(@cdir, 'x.c'))
end
def create_test_data
verbose(false) do
mkdir "testdata" unless File.exist? "testdata"
mkdir "testdata/CVS" rescue nil
mkdir "testdata/.svn" rescue nil
@cdir = "testdata/cfiles"
mkdir @cdir rescue nil
touch "testdata/.dummy"
touch "testdata/x.bak"
touch "testdata/x~"
touch "testdata/core"
touch "testdata/x.c"
touch "testdata/xyz.c"
touch "testdata/abc.c"
touch "testdata/abc.h"
touch "testdata/abc.x"
touch "testdata/existing"
end
end
end

262
test/rake/test_fileutils.rb Normal file
View file

@ -0,0 +1,262 @@
require 'rake'
require 'test/unit'
require_relative 'filecreation'
require 'fileutils'
require 'stringio'
class TestFileUtils < Test::Unit::TestCase
include FileCreation
BASEDIR = File.dirname(__FILE__)
ShellCommand = "#{BASEDIR}/shellcommand.rb"
ENV_RUBY = ENV['RUBY']
def setup
if ruby = ENV_RUBY
@oldruby = FileUtils.class_eval {remove_const :RUBY}
FileUtils.class_eval {const_set(:RUBY, ruby)}
else
@oldruby = nil
end
end
def teardown
FileUtils.rm_rf("testdata")
FileUtils::LN_SUPPORTED[0] = true
if @oldruby
ruby = @oldruby
FileUtils.class_eval {remove_const :RUBY}
FileUtils.class_eval {const_set(:RUBY, ruby)}
end
end
def test_rm_one_file
create_file("testdata/a")
FileUtils.rm_rf "testdata/a"
assert ! File.exist?("testdata/a")
end
def test_rm_two_files
create_file("testdata/a")
create_file("testdata/b")
FileUtils.rm_rf ["testdata/a", "testdata/b"]
assert ! File.exist?("testdata/a")
assert ! File.exist?("testdata/b")
end
def test_rm_filelist
list = Rake::FileList.new << "testdata/a" << "testdata/b"
list.each { |fn| create_file(fn) }
FileUtils.rm_r list
assert ! File.exist?("testdata/a")
assert ! File.exist?("testdata/b")
end
def test_ln
create_dir("testdata")
open("testdata/a", "w") { |f| f.puts "TEST_LN" }
RakeFileUtils.safe_ln("testdata/a", "testdata/b", :verbose => false)
assert_equal "TEST_LN\n", open("testdata/b") { |f| f.read }
end
class BadLink
include RakeFileUtils
attr_reader :cp_args
def initialize(klass)
@failure_class = klass
end
def cp(*args)
@cp_args = args
end
def ln(*args)
fail @failure_class, "ln not supported"
end
public :safe_ln
end
def test_safe_ln_failover_to_cp_on_standard_error
FileUtils::LN_SUPPORTED[0] = true
c = BadLink.new(StandardError)
c.safe_ln "a", "b"
assert_equal ['a', 'b'], c.cp_args
c.safe_ln "x", "y"
assert_equal ['x', 'y'], c.cp_args
end
def test_safe_ln_failover_to_cp_on_not_implemented_error
FileUtils::LN_SUPPORTED[0] = true
c = BadLink.new(NotImplementedError)
c.safe_ln "a", "b"
assert_equal ['a', 'b'], c.cp_args
end
def test_safe_ln_fails_on_script_error
FileUtils::LN_SUPPORTED[0] = true
c = BadLink.new(ScriptError)
assert_raise(ScriptError) do c.safe_ln "a", "b" end
end
def test_verbose
verbose true
assert_equal true, verbose
verbose false
assert_equal false, verbose
verbose(true) {
assert_equal true, verbose
}
assert_equal false, verbose
end
def test_nowrite
nowrite true
assert_equal true, nowrite
nowrite false
assert_equal false, nowrite
nowrite(true){
assert_equal true, nowrite
}
assert_equal false, nowrite
end
def test_file_utils_methods_are_available_at_top_level
create_file("testdata/a")
verbose(false) do
rm_rf "testdata/a"
end
assert ! File.exist?("testdata/a")
end
def test_fileutils_methods_dont_leak
obj = Object.new
assert_raise(NoMethodError) { obj.copy } # from FileUtils
assert_raise(NoMethodError) { obj.ruby } # from RubyFileUtils
end
def test_sh
verbose(false) { sh %{ruby #{ShellCommand}} }
assert true, "should not fail"
end
# If the :sh method is invoked directly from a test unit instance
# (under mini/test), the mini/test version of fail is invoked rather
# than the kernel version of fail. So we run :sh from within a
# non-test class to avoid the problem.
class Sh
include FileUtils
def run(*args)
sh(*args)
end
def self.run(*args)
new.run(*args)
end
end
def test_sh_with_a_single_string_argument
ENV['RAKE_TEST_SH'] = 'someval'
verbose(false) {
sh %{ruby #{BASEDIR}/check_expansion.rb #{env_var} someval}
}
end
def test_sh_with_multiple_arguments
ENV['RAKE_TEST_SH'] = 'someval'
verbose(false) {
Sh.run 'ruby', File.expand_path('../check_no_expansion.rb', __FILE__), env_var, 'someval'
}
end
def test_sh_failure
assert_raise(RuntimeError) {
verbose(false) { Sh.run "ruby #{File.expand_path('../shellcommand.rb', __FILE__)} 1" }
}
end
def test_sh_special_handling
count = 0
verbose(false) {
sh(%{ruby #{ShellCommand}}) do |ok, res|
assert(ok)
assert_equal 0, res.exitstatus
count += 1
end
sh(%{ruby #{ShellCommand} 1}) do |ok, res|
assert(!ok)
assert_equal 1, res.exitstatus
count += 1
end
}
assert_equal 2, count, "Block count should be 2"
end
def test_sh_noop
verbose(false) { sh %{#{ShellCommand} 1}, :noop=>true }
assert true, "should not fail"
end
def test_sh_bad_option
ex = assert_raise(ArgumentError) {
verbose(false) { sh %{#{ShellCommand}}, :bad_option=>true }
}
assert_match(/bad_option/, ex.message)
end
def test_sh_verbose
out = redirect_stderr {
verbose(true) {
sh %{#{ShellCommand}}, :noop=>true
}
}
assert_match(/^#{Regexp.quote(ShellCommand)}$/o, out)
end
def test_sh_no_verbose
out = redirect_stderr {
verbose(false) {
sh %{#{ShellCommand}}, :noop=>true
}
}
assert_equal '', out
end
def test_ruby_with_a_single_string_argument
ENV['RAKE_TEST_SH'] = 'someval'
verbose(false) {
ruby %{#{BASEDIR}/check_expansion.rb #{env_var} someval}
}
end
def test_ruby_with_multiple_arguments
ENV['RAKE_TEST_SH'] = 'someval'
verbose(false) {
ruby "#{BASEDIR}/check_no_expansion.rb", env_var, 'someval'
}
end
def test_split_all
assert_equal ['a'], RakeFileUtils.split_all('a')
assert_equal ['..'], RakeFileUtils.split_all('..')
assert_equal ['/'], RakeFileUtils.split_all('/')
assert_equal ['a', 'b'], RakeFileUtils.split_all('a/b')
assert_equal ['/', 'a', 'b'], RakeFileUtils.split_all('/a/b')
assert_equal ['..', 'a', 'b'], RakeFileUtils.split_all('../a/b')
end
private
def redirect_stderr
old_err = $stderr
$stderr = StringIO.new
yield
$stderr.string
ensure
$stderr = old_err
end
def windows?
! File::ALT_SEPARATOR.nil?
end
def env_var
windows? ? '%RAKE_TEST_SH%' : '$RAKE_TEST_SH'
end
end

57
test/rake/test_ftp.rb Normal file
View file

@ -0,0 +1,57 @@
require 'date'
require 'time'
require 'test/unit'
require 'rake/contrib/ftptools'
class FakeDate
def self.today
Date.new(2003,10,3)
end
def self.now
Time.local(2003,10,3,12,00,00)
end
end
class TestFtpFile < Test::Unit::TestCase
def setup
Rake::FtpFile.class_eval { @date_class = FakeDate; @time_class = FakeDate }
end
def test_general
file = Rake::FtpFile.new("here", "-rw-r--r-- 1 a279376 develop 121770 Mar 6 14:50 wiki.pl")
assert_equal "wiki.pl", file.name
assert_equal "here/wiki.pl", file.path
assert_equal "a279376", file.owner
assert_equal "develop", file.group
assert_equal 0644, file.mode
assert_equal 121770, file.size
assert_equal Time.mktime(2003,3,6,14,50,0,0), file.time
assert ! file.directory?
assert ! file.symlink?
end
def test_far_date
file = Rake::FtpFile.new(".", "drwxr-xr-x 3 a279376 develop 4096 Nov 26 2001 vss")
assert_equal Time.mktime(2001,11,26,0,0,0,0), file.time
end
def test_close_date
file = Rake::FtpFile.new(".", "drwxr-xr-x 3 a279376 develop 4096 Nov 26 15:35 vss")
assert_equal Time.mktime(2002,11,26,15,35,0,0), file.time
end
def test_directory
file = Rake::FtpFile.new(".", "drwxrwxr-x 9 a279376 develop 4096 Mar 13 14:32 working")
assert file.directory?
assert !file.symlink?
end
def test_symlink
file = Rake::FtpFile.new(".", "lrwxrwxrwx 1 a279376 develop 64 Mar 26 2002 xtrac -> /home/a279376/working/ics/development/java/com/fmr/fwp/ics/xtrac")
assert_equal 'xtrac', file.name
assert file.symlink?
assert !file.directory?
end
end

View file

@ -0,0 +1,75 @@
require 'test/unit'
require 'rake'
######################################################################
class TestAnEmptyInvocationChain < Test::Unit::TestCase
def setup
@empty = Rake::InvocationChain::EMPTY
end
def test_should_be_able_to_add_members
assert_nothing_raised do
@empty.append("A")
end
end
def test_to_s
assert_equal "TOP", @empty.to_s
end
end
######################################################################
class TestAnInvocationChainWithOneMember < Test::Unit::TestCase
def setup
@empty = Rake::InvocationChain::EMPTY
@first_member = "A"
@chain = @empty.append(@first_member)
end
def test_should_report_first_member_as_a_member
assert @chain.member?(@first_member)
end
def test_should_fail_when_adding_original_member
ex = assert_raise RuntimeError do
@chain.append(@first_member)
end
assert_match(/circular +dependency/i, ex.message)
assert_match(/A.*=>.*A/, ex.message)
end
def test_to_s
assert_equal "TOP => A", @chain.to_s
end
end
######################################################################
class TestAnInvocationChainWithMultipleMember < Test::Unit::TestCase
def setup
@first_member = "A"
@second_member = "B"
ch = Rake::InvocationChain::EMPTY.append(@first_member)
@chain = ch.append(@second_member)
end
def test_should_report_first_member_as_a_member
assert @chain.member?(@first_member)
end
def test_should_report_second_member_as_a_member
assert @chain.member?(@second_member)
end
def test_should_fail_when_adding_original_member
ex = assert_raise RuntimeError do
@chain.append(@first_member)
end
assert_match(/A.*=>.*B.*=>.*A/, ex.message)
end
end

View file

@ -0,0 +1,24 @@
require 'test/unit'
require 'rake'
require 'rake/loaders/makefile'
class TestMakefileLoader < Test::Unit::TestCase
include Rake
def test_parse
Task.clear
loader = Rake::MakefileLoader.new
loader.load("#{File.dirname(__FILE__)}/data/sample.mf")
%w(a b c d).each do |t|
assert Task.task_defined?(t), "#{t} should be a defined task"
end
assert_equal %w(a1 a2 a3 a4 a5 a6 a7).sort, Task['a'].prerequisites.sort
assert_equal %w(b1 b2 b3 b4 b5 b6 b7).sort, Task['b'].prerequisites.sort
assert_equal %w(c1).sort, Task['c'].prerequisites.sort
assert_equal %w(d1 d2).sort, Task['d'].prerequisites.sort
assert_equal %w(e1 f1).sort, Task['e'].prerequisites.sort
assert_equal %w(e1 f1).sort, Task['f'].prerequisites.sort
assert_equal ["g1", "g 2", "g 3", "g4"].sort, Task['g 0'].prerequisites.sort
assert_equal 7, Task.tasks.size
end
end

View file

@ -0,0 +1,43 @@
require 'test/unit'
require 'rake'
######################################################################
class TestMultiTask < Test::Unit::TestCase
include Rake
def setup
Task.clear
@runs = Array.new
end
def test_running_multitasks
task :a do 3.times do |i| @runs << "A#{i}"; sleep 0.01; end end
task :b do 3.times do |i| @runs << "B#{i}"; sleep 0.01; end end
multitask :both => [:a, :b]
Task[:both].invoke
assert_equal 6, @runs.size
assert @runs.index("A0") < @runs.index("A1")
assert @runs.index("A1") < @runs.index("A2")
assert @runs.index("B0") < @runs.index("B1")
assert @runs.index("B1") < @runs.index("B2")
end
def test_all_multitasks_wait_on_slow_prerequisites
task :slow do 3.times do |i| @runs << "S#{i}"; sleep 0.05 end end
task :a => [:slow] do 3.times do |i| @runs << "A#{i}"; sleep 0.01 end end
task :b => [:slow] do 3.times do |i| @runs << "B#{i}"; sleep 0.01 end end
multitask :both => [:a, :b]
Task[:both].invoke
assert_equal 9, @runs.size
assert @runs.index("S0") < @runs.index("S1")
assert @runs.index("S1") < @runs.index("S2")
assert @runs.index("S2") < @runs.index("A0")
assert @runs.index("S2") < @runs.index("B0")
assert @runs.index("A0") < @runs.index("A1")
assert @runs.index("A1") < @runs.index("A2")
assert @runs.index("B0") < @runs.index("B1")
assert @runs.index("B1") < @runs.index("B2")
end
end

44
test/rake/test_namespace.rb Executable file
View file

@ -0,0 +1,44 @@
require 'test/unit'
require 'rake'
class TestNameSpace < Test::Unit::TestCase
class TM
include Rake::TaskManager
end
def test_namespace_creation
mgr = TM.new
ns = Rake::NameSpace.new(mgr, [])
assert_not_nil ns
end
def test_namespace_lookup
mgr = TM.new
ns = mgr.in_namespace("n") do
mgr.define_task(Rake::Task, "t")
end
assert_not_nil ns["t"]
assert_equal mgr["n:t"], ns["t"]
end
def test_namespace_reports_tasks_it_owns
mgr = TM.new
nns = nil
ns = mgr.in_namespace("n") do
mgr.define_task(Rake::Task, :x)
mgr.define_task(Rake::Task, :y)
nns = mgr.in_namespace("nn") do
mgr.define_task(Rake::Task, :z)
end
end
mgr.in_namespace("m") do
mgr.define_task(Rake::Task, :x)
end
assert_equal ["n:nn:z", "n:x", "n:y"],
ns.tasks.map { |tsk| tsk.name }
assert_equal ["n:nn:z"], nns.tasks.map {|t| t.name}
end
end

View file

@ -0,0 +1,105 @@
require 'test/unit'
require 'rake/packagetask'
class TestPackageTask < Test::Unit::TestCase
include Rake
def test_create
pkg = Rake::PackageTask.new("pkgr", "1.2.3") { |p|
p.package_files << "install.rb"
p.package_files.include(
'[A-Z]*',
'bin/**/*',
'lib/**/*.rb',
'test/**/*.rb',
'doc/**/*',
'build/rubyapp.rb',
'*.blurb')
p.package_files.exclude(/\bCVS\b/)
p.package_files.exclude(/~$/)
p.package_dir = 'pkg'
p.need_tar = true
p.need_tar_gz = true
p.need_tar_bz2 = true
p.need_zip = true
}
assert_equal "pkg", pkg.package_dir
assert pkg.package_files.include?("bin/rake")
assert "pkgr", pkg.name
assert "1.2.3", pkg.version
assert Task[:package]
assert Task['pkg/pkgr-1.2.3.tgz']
assert Task['pkg/pkgr-1.2.3.tar.gz']
assert Task['pkg/pkgr-1.2.3.tar.bz2']
assert Task['pkg/pkgr-1.2.3.zip']
assert Task["pkg/pkgr-1.2.3"]
assert Task[:clobber_package]
assert Task[:repackage]
end
def test_missing_version
assert_raise(RuntimeError) {
pkg = Rake::PackageTask.new("pkgr") { |p| }
}
end
def test_no_version
pkg = Rake::PackageTask.new("pkgr", :noversion) { |p| }
assert "pkgr", pkg.send(:package_name)
end
def test_clone
pkg = Rake::PackageTask.new("x", :noversion)
p2 = pkg.clone
pkg.package_files << "y"
p2.package_files << "x"
assert_equal ["y"], pkg.package_files
assert_equal ["x"], p2.package_files
end
end
require 'rake/gempackagetask'
class TestGemPackageTask < Test::Unit::TestCase
def test_gem_package
gem = Gem::Specification.new do |g|
g.name = "pkgr"
g.version = "1.2.3"
g.files = FileList["x"].resolve
end
pkg = Rake::GemPackageTask.new(gem) do |p|
p.package_files << "y"
end
assert_equal ["x", "y"], pkg.package_files
assert_equal "pkgr-1.2.3.gem", pkg.gem_file
end
def test_gem_package_with_current_platform
gem = Gem::Specification.new do |g|
g.name = "pkgr"
g.version = "1.2.3"
g.files = FileList["x"].resolve
g.platform = Gem::Platform::CURRENT
end
pkg = Rake::GemPackageTask.new(gem) do |p|
p.package_files << "y"
end
assert_equal ["x", "y"], pkg.package_files
assert_match(/^pkgr-1\.2\.3-(\S+)\.gem$/, pkg.gem_file)
end
def test_gem_package_with_ruby_platform
gem = Gem::Specification.new do |g|
g.name = "pkgr"
g.version = "1.2.3"
g.files = FileList["x"].resolve
g.platform = Gem::Platform::RUBY
end
pkg = Rake::GemPackageTask.new(gem) do |p|
p.package_files << "y"
end
assert_equal ["x", "y"], pkg.package_files
assert_equal "pkgr-1.2.3.gem", pkg.gem_file
end
end

207
test/rake/test_pathmap.rb Normal file
View file

@ -0,0 +1,207 @@
require 'test/unit'
require 'rake'
# ====================================================================
class TestPathMap < Test::Unit::TestCase
def test_returns_self_with_no_args
assert_equal "abc.rb", "abc.rb".pathmap
end
def test_s_returns_file_separator
sep = File::ALT_SEPARATOR || File::SEPARATOR
assert_equal sep, "abc.rb".pathmap("%s")
assert_equal sep, "".pathmap("%s")
assert_equal "a#{sep}b", "a/b".pathmap("%d%s%f")
end
def test_f_returns_basename
assert_equal "abc.rb", "abc.rb".pathmap("%f")
assert_equal "abc.rb", "this/is/a/dir/abc.rb".pathmap("%f")
assert_equal "abc.rb", "/this/is/a/dir/abc.rb".pathmap("%f")
end
def test_n_returns_basename_without_extension
assert_equal "abc", "abc.rb".pathmap("%n")
assert_equal "abc", "abc".pathmap("%n")
assert_equal "abc", "this/is/a/dir/abc.rb".pathmap("%n")
assert_equal "abc", "/this/is/a/dir/abc.rb".pathmap("%n")
assert_equal "abc", "/this/is/a/dir/abc".pathmap("%n")
end
def test_d_returns_dirname
assert_equal ".", "abc.rb".pathmap("%d")
assert_equal "/", "/abc".pathmap("%d")
assert_equal "this/is/a/dir", "this/is/a/dir/abc.rb".pathmap("%d")
assert_equal "/this/is/a/dir", "/this/is/a/dir/abc.rb".pathmap("%d")
end
def test_9d_returns_partial_dirname
assert_equal "this/is", "this/is/a/dir/abc.rb".pathmap("%2d")
assert_equal "this", "this/is/a/dir/abc.rb".pathmap("%1d")
assert_equal ".", "this/is/a/dir/abc.rb".pathmap("%0d")
assert_equal "dir", "this/is/a/dir/abc.rb".pathmap("%-1d")
assert_equal "a/dir", "this/is/a/dir/abc.rb".pathmap("%-2d")
assert_equal "this/is/a/dir", "this/is/a/dir/abc.rb".pathmap("%100d")
assert_equal "this/is/a/dir", "this/is/a/dir/abc.rb".pathmap("%-100d")
end
def test_x_returns_extension
assert_equal "", "abc".pathmap("%x")
assert_equal ".rb", "abc.rb".pathmap("%x")
assert_equal ".rb", "abc.xyz.rb".pathmap("%x")
assert_equal "", ".depends".pathmap("%x")
assert_equal "", "dir/.depends".pathmap("%x")
end
def test_X_returns_everything_but_extension
assert_equal "abc", "abc".pathmap("%X")
assert_equal "abc", "abc.rb".pathmap("%X")
assert_equal "abc.xyz", "abc.xyz.rb".pathmap("%X")
assert_equal "ab.xyz", "ab.xyz.rb".pathmap("%X")
assert_equal "a.xyz", "a.xyz.rb".pathmap("%X")
assert_equal "abc", "abc.rb".pathmap("%X")
assert_equal "ab", "ab.rb".pathmap("%X")
assert_equal "a", "a.rb".pathmap("%X")
assert_equal ".depends", ".depends".pathmap("%X")
assert_equal "a/dir/.depends", "a/dir/.depends".pathmap("%X")
assert_equal "/.depends", "/.depends".pathmap("%X")
end
def test_p_returns_entire_pathname
assert_equal "abc.rb", "abc.rb".pathmap("%p")
assert_equal "this/is/a/dir/abc.rb", "this/is/a/dir/abc.rb".pathmap("%p")
assert_equal "/this/is/a/dir/abc.rb", "/this/is/a/dir/abc.rb".pathmap("%p")
end
def test_dash_returns_empty_string
assert_equal "", "abc.rb".pathmap("%-")
assert_equal "abc.rb", "abc.rb".pathmap("%X%-%x")
end
def test_percent_percent_returns_percent
assert_equal "a%b", "".pathmap("a%%b")
end
def test_undefined_percent_causes_error
ex = assert_raise(ArgumentError) {
"dir/abc.rb".pathmap("%z")
}
end
def test_pattern_returns_substitutions
assert_equal "bin/org/osb",
"src/org/osb/Xyz.java".pathmap("%{src,bin}d")
end
def test_pattern_can_use_backreferences
assert_equal "dir/hi/is", "dir/this/is".pathmap("%{t(hi)s,\\1}p")
end
def test_pattern_with_star_replacement_string_uses_block
assert_equal "src/ORG/osb",
"src/org/osb/Xyz.java".pathmap("%{/org,*}d") { |d| d.upcase }
assert_equal "Xyz.java",
"src/org/osb/Xyz.java".pathmap("%{.*,*}f") { |f| f.capitalize }
end
def test_pattern_with_no_replacement_nor_block_substitutes_empty_string
assert_equal "bc.rb", "abc.rb".pathmap("%{a}f")
end
def test_pattern_works_with_certain_valid_operators
assert_equal "dir/xbc.rb", "dir/abc.rb".pathmap("%{a,x}p")
assert_equal "d1r", "dir/abc.rb".pathmap("%{i,1}d")
assert_equal "xbc.rb", "dir/abc.rb".pathmap("%{a,x}f")
assert_equal ".Rb", "dir/abc.rb".pathmap("%{r,R}x")
assert_equal "xbc", "dir/abc.rb".pathmap("%{a,x}n")
end
def test_multiple_patterns
assert_equal "this/is/b/directory/abc.rb",
"this/is/a/dir/abc.rb".pathmap("%{a,b;dir,\\0ectory}p")
end
def test_partial_directory_selection_works_with_patterns
assert_equal "this/is/a/long",
"this/is/a/really/long/path/ok.rb".pathmap("%{/really/,/}5d")
end
def test_pattern_with_invalid_operator
ex = assert_raise(ArgumentError) do
"abc.xyz".pathmap("%{src,bin}z")
end
assert_match(/unknown.*pathmap.*spec.*z/i, ex.message)
end
def test_works_with_windows_separators
if File::ALT_SEPARATOR
assert_equal "abc", 'dir\abc.rb'.pathmap("%n")
assert_equal 'this\is\a\dir',
'this\is\a\dir\abc.rb'.pathmap("%d")
end
end
def test_complex_patterns
sep = "".pathmap("%s")
assert_equal "dir/abc.rb", "dir/abc.rb".pathmap("%d/%n%x")
assert_equal "./abc.rb", "abc.rb".pathmap("%d/%n%x")
assert_equal "Your file extension is '.rb'",
"dir/abc.rb".pathmap("Your file extension is '%x'")
assert_equal "bin/org/onstepback/proj/A.class",
"src/org/onstepback/proj/A.java".pathmap("%{src,bin}d/%n.class")
assert_equal "src_work/bin/org/onstepback/proj/A.class",
"src_work/src/org/onstepback/proj/A.java".pathmap('%{\bsrc\b,bin}X.class')
assert_equal ".depends.bak", ".depends".pathmap("%X.bak")
assert_equal "d#{sep}a/b/c#{sep}file.txt", "a/b/c/d/file.txt".pathmap("%-1d%s%3d%s%f")
end
end
class TestPathMapExplode < Test::Unit::TestCase
def setup
String.class_eval { public :pathmap_explode }
end
def teardown
String.class_eval { protected :pathmap_explode }
end
def test_explode
assert_equal ['a'], 'a'.pathmap_explode
assert_equal ['a', 'b'], 'a/b'.pathmap_explode
assert_equal ['a', 'b', 'c'], 'a/b/c'.pathmap_explode
assert_equal ['/', 'a'], '/a'.pathmap_explode
assert_equal ['/', 'a', 'b'], '/a/b'.pathmap_explode
assert_equal ['/', 'a', 'b', 'c'], '/a/b/c'.pathmap_explode
if File::ALT_SEPARATOR
assert_equal ['c:.', 'a'], 'c:a'.pathmap_explode
assert_equal ['c:.', 'a', 'b'], 'c:a/b'.pathmap_explode
assert_equal ['c:.', 'a', 'b', 'c'], 'c:a/b/c'.pathmap_explode
assert_equal ['c:/', 'a'], 'c:/a'.pathmap_explode
assert_equal ['c:/', 'a', 'b'], 'c:/a/b'.pathmap_explode
assert_equal ['c:/', 'a', 'b', 'c'], 'c:/a/b/c'.pathmap_explode
end
end
end
class TestPathMapPartial < Test::Unit::TestCase
def test_pathmap_partial
@path = "1/2/file"
def @path.call(n)
pathmap_partial(n)
end
assert_equal("1", @path.call(1))
assert_equal("1/2", @path.call(2))
assert_equal("1/2", @path.call(3))
assert_equal(".", @path.call(0))
assert_equal("2", @path.call(-1))
assert_equal("1/2", @path.call(-2))
assert_equal("1/2", @path.call(-3))
end
end
class TestFileListPathMap < Test::Unit::TestCase
def test_file_list_supports_pathmap
assert_equal ['a', 'b'], FileList['dir/a.rb', 'dir/b.rb'].pathmap("%n")
end
end

View file

@ -0,0 +1,23 @@
require 'test/unit'
require 'rake'
require_relative 'capture_stdout'
class PseudoStatusTest < Test::Unit::TestCase
def test_with_zero_exit_status
s = Rake::PseudoStatus.new
assert_equal 0, s.exitstatus
assert_equal 0, s.to_i
assert_equal 0, s >> 8
assert ! s.stopped?
assert s.exited?
end
def test_with_99_exit_status
s = Rake::PseudoStatus.new(99)
assert_equal 99, s.exitstatus
assert_equal 25344, s.to_i
assert_equal 99, s >> 8
assert ! s.stopped?
assert s.exited?
end
end

39
test/rake/test_rake.rb Normal file
View file

@ -0,0 +1,39 @@
require 'test/unit'
require 'rake'
class TestRake < Test::Unit::TestCase
def test_each_dir_parent
assert_equal ['a'], alldirs('a')
assert_equal ['a/b', 'a'], alldirs('a/b')
assert_equal ['/a/b', '/a', '/'], alldirs('/a/b')
if File.dirname("c:/foo") == "c:"
# Under Unix
assert_equal ['c:/a/b', 'c:/a', 'c:'], alldirs('c:/a/b')
assert_equal ['c:a/b', 'c:a'], alldirs('c:a/b')
else
# Under Windows
assert_equal ['c:/a/b', 'c:/a', 'c:/'], alldirs('c:/a/b')
assert_equal ['c:a/b', 'c:a'], alldirs('c:a/b')
end
end
def alldirs(fn)
result = []
Rake.each_dir_parent(fn) { |d| result << d }
result
end
def test_can_override_application
old_app = Rake.application
fake_app = Object.new
Rake.application = fake_app
assert_equal fake_app, Rake.application
ensure
Rake.application = old_app
end
def test_original_dir_reports_current_dir
assert_equal Dir.pwd, Rake.original_dir
end
end

View file

@ -0,0 +1,84 @@
require 'test/unit'
require 'rake/rdoctask'
class TestRDocTask < Test::Unit::TestCase
include Rake
def setup
Task.clear
end
def test_tasks_creation
Rake::RDocTask.new
assert Task[:rdoc]
assert Task[:clobber_rdoc]
assert Task[:rerdoc]
end
def test_tasks_creation_with_custom_name_symbol
rd = Rake::RDocTask.new(:rdoc_dev)
assert Task[:rdoc_dev]
assert Task[:clobber_rdoc_dev]
assert Task[:rerdoc_dev]
assert_equal :rdoc_dev, rd.name
end
def test_tasks_creation_with_custom_name_string
rd = Rake::RDocTask.new("rdoc_dev")
assert Task[:rdoc_dev]
assert Task[:clobber_rdoc_dev]
assert Task[:rerdoc_dev]
assert_equal "rdoc_dev", rd.name
end
def test_tasks_creation_with_custom_name_hash
options = { :rdoc => "rdoc", :clobber_rdoc => "rdoc:clean", :rerdoc => "rdoc:force" }
rd = Rake::RDocTask.new(options)
assert Task[:"rdoc"]
assert Task[:"rdoc:clean"]
assert Task[:"rdoc:force"]
assert_raises(RuntimeError) { Task[:clobber_rdoc] }
assert_equal options, rd.name
end
def test_tasks_creation_with_custom_name_hash_will_use_default_if_an_option_isnt_given
rd = Rake::RDocTask.new(:clobber_rdoc => "rdoc:clean")
assert Task[:rdoc]
assert Task[:"rdoc:clean"]
assert Task[:rerdoc]
end
def test_tasks_creation_with_custom_name_hash_raises_exception_if_invalid_option_given
assert_raises(ArgumentError) do
Rake::RDocTask.new(:foo => "bar")
end
begin
Rake::RDocTask.new(:foo => "bar")
rescue ArgumentError => e
assert_match(/foo/, e.message)
end
end
def test_inline_source_is_enabled_by_default
rd = Rake::RDocTask.new
assert rd.option_list.include?('--inline-source')
end
def test_inline_source_option_is_only_appended_if_option_not_already_given
rd = Rake::RDocTask.new
rd.options << '--inline-source'
assert_equal 1, rd.option_list.grep('--inline-source').size
rd = Rake::RDocTask.new
rd.options << '-S'
assert_equal 1, rd.option_list.grep('-S').size
assert_equal 0, rd.option_list.grep('--inline-source').size
end
def test_inline_source_option_can_be_disabled
rd = Rake::RDocTask.new
rd.inline_source = false
assert !rd.option_list.include?('--inline-source')
end
end

32
test/rake/test_require.rb Normal file
View file

@ -0,0 +1,32 @@
require 'test/unit'
require 'rake'
# ====================================================================
class TestRequire < Test::Unit::TestCase
RakeLibDir = File.dirname(__FILE__) + '/data/rakelib'
def test_can_load_rake_library
app = Rake::Application.new
assert app.instance_eval {
rake_require("test1", [RakeLibDir], [])
}
end
def test_wont_reload_rake_library
app = Rake::Application.new
assert ! app.instance_eval {
rake_require("test2", [RakeLibDir], ['test2'])
}
end
def test_throws_error_if_library_not_found
app = Rake::Application.new
ex = assert_raise(LoadError) {
assert app.instance_eval {
rake_require("testx", [RakeLibDir], [])
}
}
assert_match(/x/, ex.message)
end
end

345
test/rake/test_rules.rb Normal file
View file

@ -0,0 +1,345 @@
require 'test/unit'
require 'fileutils'
require 'rake'
require_relative 'filecreation'
######################################################################
class TestRules < Test::Unit::TestCase
include Rake
include FileCreation
SRCFILE = "testdata/abc.c"
SRCFILE2 = "testdata/xyz.c"
FTNFILE = "testdata/abc.f"
OBJFILE = "testdata/abc.o"
FOOFILE = "testdata/foo"
DOTFOOFILE = "testdata/.foo"
def setup
Task.clear
@runs = []
end
def teardown
FileList['testdata/*'].uniq.each do |f| rm_r(f, :verbose=>false) end
end
def test_multiple_rules1
create_file(FTNFILE)
delete_file(SRCFILE)
delete_file(OBJFILE)
rule(/\.o$/ => ['.c']) do @runs << :C end
rule(/\.o$/ => ['.f']) do @runs << :F end
t = Task[OBJFILE]
t.invoke
Task[OBJFILE].invoke
assert_equal [:F], @runs
end
def test_multiple_rules2
create_file(FTNFILE)
delete_file(SRCFILE)
delete_file(OBJFILE)
rule(/\.o$/ => ['.f']) do @runs << :F end
rule(/\.o$/ => ['.c']) do @runs << :C end
Task[OBJFILE].invoke
assert_equal [:F], @runs
end
def test_create_with_source
create_file(SRCFILE)
rule(/\.o$/ => ['.c']) do |t|
@runs << t.name
assert_equal OBJFILE, t.name
assert_equal SRCFILE, t.source
end
Task[OBJFILE].invoke
assert_equal [OBJFILE], @runs
end
def test_single_dependent
create_file(SRCFILE)
rule(/\.o$/ => '.c') do |t|
@runs << t.name
end
Task[OBJFILE].invoke
assert_equal [OBJFILE], @runs
end
def test_rule_can_be_created_by_string
create_file(SRCFILE)
rule '.o' => ['.c'] do |t|
@runs << t.name
end
Task[OBJFILE].invoke
assert_equal [OBJFILE], @runs
end
def test_rule_prereqs_can_be_created_by_string
create_file(SRCFILE)
rule '.o' => '.c' do |t|
@runs << t.name
end
Task[OBJFILE].invoke
assert_equal [OBJFILE], @runs
end
def test_plain_strings_as_dependents_refer_to_files
create_file(SRCFILE)
rule '.o' => SRCFILE do |t|
@runs << t.name
end
Task[OBJFILE].invoke
assert_equal [OBJFILE], @runs
end
def test_file_names_beginning_with_dot_can_be_tricked_into_refering_to_file
verbose(false) do
chdir("testdata") do
create_file('.foo')
rule '.o' => "./.foo" do |t|
@runs << t.name
end
Task[OBJFILE].invoke
assert_equal [OBJFILE], @runs
end
end
end
def test_file_names_beginning_with_dot_can_be_wrapped_in_lambda
verbose(false) do
chdir("testdata") do
create_file(".foo")
rule '.o' => lambda{".foo"} do |t|
@runs << "#{t.name} - #{t.source}"
end
Task[OBJFILE].invoke
assert_equal ["#{OBJFILE} - .foo"], @runs
end
end
end
def test_file_names_containing_percent_can_be_wrapped_in_lambda
verbose(false) do
chdir("testdata") do
create_file("foo%x")
rule '.o' => lambda{"foo%x"} do |t|
@runs << "#{t.name} - #{t.source}"
end
Task[OBJFILE].invoke
assert_equal ["#{OBJFILE} - foo%x"], @runs
end
end
end
def test_non_extension_rule_name_refers_to_file
verbose(false) do
chdir("testdata") do
create_file("abc.c")
rule "abc" => '.c' do |t|
@runs << t.name
end
Task["abc"].invoke
assert_equal ["abc"], @runs
end
end
end
def test_pathmap_automatically_applies_to_name
verbose(false) do
chdir("testdata") do
create_file("zzabc.c")
rule ".o" => 'zz%{x,a}n.c' do |t|
@runs << "#{t.name} - #{t.source}"
end
Task["xbc.o"].invoke
assert_equal ["xbc.o - zzabc.c"], @runs
end
end
end
def test_plain_strings_are_just_filenames
verbose(false) do
chdir("testdata") do
create_file("plainname")
rule ".o" => 'plainname' do |t|
@runs << "#{t.name} - #{t.source}"
end
Task["xbc.o"].invoke
assert_equal ["xbc.o - plainname"], @runs
end
end
end
def test_rule_runs_when_explicit_task_has_no_actions
create_file(SRCFILE)
create_file(SRCFILE2)
delete_file(OBJFILE)
rule '.o' => '.c' do |t|
@runs << t.source
end
file OBJFILE => [SRCFILE2]
Task[OBJFILE].invoke
assert_equal [SRCFILE], @runs
end
def test_close_matches_on_name_do_not_trigger_rule
create_file("testdata/x.c")
rule '.o' => ['.c'] do |t|
@runs << t.name
end
assert_raise(RuntimeError) { Task['testdata/x.obj'].invoke }
assert_raise(RuntimeError) { Task['testdata/x.xyo'].invoke }
end
def test_rule_rebuilds_obj_when_source_is_newer
create_timed_files(OBJFILE, SRCFILE)
rule(/\.o$/ => ['.c']) do
@runs << :RULE
end
Task[OBJFILE].invoke
assert_equal [:RULE], @runs
end
def test_rule_with_two_sources_runs_if_both_sources_are_present
create_timed_files(OBJFILE, SRCFILE, SRCFILE2)
rule OBJFILE => [lambda{SRCFILE}, lambda{SRCFILE2}] do
@runs << :RULE
end
Task[OBJFILE].invoke
assert_equal [:RULE], @runs
end
def test_rule_with_two_sources_but_one_missing_does_not_run
create_timed_files(OBJFILE, SRCFILE)
delete_file(SRCFILE2)
rule OBJFILE => [lambda{SRCFILE}, lambda{SRCFILE2}] do
@runs << :RULE
end
Task[OBJFILE].invoke
assert_equal [], @runs
end
def test_rule_with_two_sources_builds_both_sources
task 'x.aa'
task 'x.bb'
rule '.a' => '.aa' do
@runs << "A"
end
rule '.b' => '.bb' do
@runs << "B"
end
rule ".c" => ['.a', '.b'] do
@runs << "C"
end
Task["x.c"].invoke
assert_equal ["A", "B", "C"], @runs.sort
end
def test_second_rule_runs_when_first_rule_doesnt
create_timed_files(OBJFILE, SRCFILE)
delete_file(SRCFILE2)
rule OBJFILE => [lambda{SRCFILE}, lambda{SRCFILE2}] do
@runs << :RULE1
end
rule OBJFILE => [lambda{SRCFILE}] do
@runs << :RULE2
end
Task[OBJFILE].invoke
assert_equal [:RULE2], @runs
end
def test_second_rule_doest_run_if_first_triggers
create_timed_files(OBJFILE, SRCFILE, SRCFILE2)
rule OBJFILE => [lambda{SRCFILE}, lambda{SRCFILE2}] do
@runs << :RULE1
end
rule OBJFILE => [lambda{SRCFILE}] do
@runs << :RULE2
end
Task[OBJFILE].invoke
assert_equal [:RULE1], @runs
end
def test_second_rule_doest_run_if_first_triggers_with_reversed_rules
create_timed_files(OBJFILE, SRCFILE, SRCFILE2)
rule OBJFILE => [lambda{SRCFILE}] do
@runs << :RULE1
end
rule OBJFILE => [lambda{SRCFILE}, lambda{SRCFILE2}] do
@runs << :RULE2
end
Task[OBJFILE].invoke
assert_equal [:RULE1], @runs
end
def test_rule_with_proc_dependent_will_trigger
ran = false
mkdir_p("testdata/src/jw")
create_file("testdata/src/jw/X.java")
rule %r(classes/.*\.class) => [
proc { |fn| fn.pathmap("%{classes,testdata/src}d/%n.java") }
] do |task|
assert_equal task.name, 'classes/jw/X.class'
assert_equal task.source, 'testdata/src/jw/X.java'
@runs << :RULE
end
Task['classes/jw/X.class'].invoke
assert_equal [:RULE], @runs
ensure
rm_r("testdata/src", :verbose=>false) rescue nil
end
def test_proc_returning_lists_are_flattened_into_prereqs
ran = false
mkdir_p("testdata/flatten")
create_file("testdata/flatten/a.txt")
task 'testdata/flatten/b.data' do |t|
ran = true
touch t.name, :verbose => false
end
rule '.html' =>
proc { |fn|
[
fn.ext("txt"),
"testdata/flatten/b.data"
]
} do |task|
end
Task['testdata/flatten/a.html'].invoke
assert ran, "Should have triggered flattened dependency"
ensure
rm_r("testdata/flatten", :verbose=>false) rescue nil
end
def test_recursive_rules_will_work_as_long_as_they_terminate
actions = []
create_file("testdata/abc.xml")
rule '.y' => '.xml' do actions << 'y' end
rule '.c' => '.y' do actions << 'c'end
rule '.o' => '.c' do actions << 'o'end
rule '.exe' => '.o' do actions << 'exe'end
Task["testdata/abc.exe"].invoke
assert_equal ['y', 'c', 'o', 'exe'], actions
end
def test_recursive_rules_that_dont_terminate_will_overflow
create_file("testdata/a.a")
prev = 'a'
('b'..'z').each do |letter|
rule ".#{letter}" => ".#{prev}" do |t| puts "#{t.name}" end
prev = letter
end
ex = assert_raise(Rake::RuleRecursionOverflowError) {
Task["testdata/a.z"].invoke
}
assert_match(/a\.z => testdata\/a.y/, ex.message)
end
def test_rules_with_bad_dependents_will_fail
rule "a" => [ 1 ] do |t| puts t.name end
assert_raise(RuntimeError) do Task['a'].invoke end
end
end

View file

@ -0,0 +1,87 @@
require 'test/unit'
require 'rake'
######################################################################
class TestTaskArguments < Test::Unit::TestCase
def teardown
ENV.delete('rev')
ENV.delete('VER')
end
def test_empty_arg_list_is_empty
ta = Rake::TaskArguments.new([], [])
assert_equal({}, ta.to_hash)
end
def test_multiple_values_in_args
ta = Rake::TaskArguments.new([:a, :b, :c], [:one, :two, :three])
assert_equal({:a => :one, :b => :two, :c => :three}, ta.to_hash)
end
def test_to_s
ta = Rake::TaskArguments.new([:a, :b, :c], [1, 2, 3])
assert_equal ta.to_hash.inspect, ta.to_s
assert_equal ta.to_hash.inspect, ta.inspect
end
def test_enumerable_behavior
ta = Rake::TaskArguments.new([:a, :b, :c], [1, 2 ,3])
assert_equal [10, 20, 30], ta.collect { |k,v| v * 10 }.sort
end
def test_named_args
ta = Rake::TaskArguments.new(["aa", "bb"], [1, 2])
assert_equal 1, ta.aa
assert_equal 1, ta[:aa]
assert_equal 1, ta["aa"]
assert_equal 2, ta.bb
assert_nil ta.cc
end
def test_args_knows_its_names
ta = Rake::TaskArguments.new(["aa", "bb"], [1, 2])
assert_equal ["aa", "bb"], ta.names
end
def test_extra_names_are_nil
ta = Rake::TaskArguments.new(["aa", "bb", "cc"], [1, 2])
assert_nil ta.cc
end
def test_args_can_reference_env_values
ta = Rake::TaskArguments.new(["aa"], [1])
ENV['rev'] = "1.2"
ENV['VER'] = "2.3"
assert_equal "1.2", ta.rev
assert_equal "2.3", ta.ver
end
def test_creating_new_argument_scopes
parent = Rake::TaskArguments.new(['p'], [1])
child = parent.new_scope(['c', 'p'])
assert_equal({:p=>1}, child.to_hash)
assert_equal 1, child.p
assert_equal 1, child["p"]
assert_equal 1, child[:p]
assert_nil child.c
end
def test_child_hides_parent_arg_names
parent = Rake::TaskArguments.new(['aa'], [1])
child = Rake::TaskArguments.new(['aa'], [2], parent)
assert_equal 2, child.aa
end
def test_default_arguments_values_can_be_merged
ta = Rake::TaskArguments.new(["aa", "bb"], [nil, "original_val"])
ta.with_defaults({ :aa => 'default_val' })
assert_equal 'default_val', ta[:aa]
assert_equal 'original_val', ta[:bb]
end
def test_default_arguements_that_dont_match_names_are_ignored
ta = Rake::TaskArguments.new(["aa", "bb"], [nil, "original_val"])
ta.with_defaults({ "cc" => "default_val" })
assert_nil ta[:cc]
end
end

View file

@ -0,0 +1,169 @@
require 'test/unit'
require 'rake'
class TaskManager
include Rake::TaskManager
end
class TestTaskManager < Test::Unit::TestCase
def setup
@tm = TaskManager.new
end
def test_create_task_manager
assert_not_nil @tm
assert_equal [], @tm.tasks
end
def test_define_task
t = @tm.define_task(Rake::Task, :t)
assert_equal "t", t.name
assert_equal @tm, t.application
end
def test_name_lookup
t = @tm.define_task(Rake::Task, :t)
assert_equal t, @tm[:t]
end
def test_namespace_task_create
@tm.in_namespace("x") do
t = @tm.define_task(Rake::Task, :t)
assert_equal "x:t", t.name
end
assert_equal ["x:t"], @tm.tasks.collect { |t| t.name }
end
def test_anonymous_namespace
anon_ns = @tm.in_namespace(nil) do
t = @tm.define_task(Rake::Task, :t)
assert_equal "_anon_1:t", t.name
end
task = anon_ns[:t]
assert_equal "_anon_1:t", task.name
end
def test_create_filetask_in_namespace
@tm.in_namespace("x") do
t = @tm.define_task(Rake::FileTask, "fn")
assert_equal "fn", t.name
end
assert_equal ["fn"], @tm.tasks.collect { |t| t.name }
end
def test_namespace_yields_same_namespace_as_returned
yielded_namespace = nil
returned_namespace = @tm.in_namespace("x") do |ns|
yielded_namespace = ns
end
assert_equal returned_namespace, yielded_namespace
end
def test_name_lookup_with_implicit_file_tasks
t = @tm["README"]
assert_equal "README", t.name
assert Rake::FileTask === t
end
def test_name_lookup_with_nonexistent_task
assert_raise(RuntimeError) {
t = @tm["DOES NOT EXIST"]
}
end
def test_name_lookup_in_multiple_scopes
aa = nil
bb = nil
xx = @tm.define_task(Rake::Task, :xx)
top_z = @tm.define_task(Rake::Task, :z)
@tm.in_namespace("a") do
aa = @tm.define_task(Rake::Task, :aa)
mid_z = @tm.define_task(Rake::Task, :z)
@tm.in_namespace("b") do
bb = @tm.define_task(Rake::Task, :bb)
bot_z = @tm.define_task(Rake::Task, :z)
assert_equal ["a", "b"], @tm.current_scope
assert_equal bb, @tm["a:b:bb"]
assert_equal aa, @tm["a:aa"]
assert_equal xx, @tm["xx"]
assert_equal bot_z, @tm["z"]
assert_equal mid_z, @tm["^z"]
assert_equal top_z, @tm["^^z"]
assert_equal top_z, @tm["rake:z"]
end
assert_equal ["a"], @tm.current_scope
assert_equal bb, @tm["a:b:bb"]
assert_equal aa, @tm["a:aa"]
assert_equal xx, @tm["xx"]
assert_equal bb, @tm["b:bb"]
assert_equal aa, @tm["aa"]
assert_equal mid_z, @tm["z"]
assert_equal top_z, @tm["^z"]
assert_equal top_z, @tm["rake:z"]
end
assert_equal [], @tm.current_scope
assert_equal [], xx.scope
assert_equal ['a'], aa.scope
assert_equal ['a', 'b'], bb.scope
end
def test_lookup_with_explicit_scopes
t1, t2, t3, s = (0...4).collect { nil }
t1 = @tm.define_task(Rake::Task, :t)
@tm.in_namespace("a") do
t2 = @tm.define_task(Rake::Task, :t)
s = @tm.define_task(Rake::Task, :s)
@tm.in_namespace("b") do
t3 = @tm.define_task(Rake::Task, :t)
end
end
assert_equal t1, @tm[:t, []]
assert_equal t2, @tm[:t, ["a"]]
assert_equal t3, @tm[:t, ["a", "b"]]
assert_equal s, @tm[:s, ["a", "b"]]
assert_equal s, @tm[:s, ["a"]]
end
def test_correctly_scoped_prerequisites_are_invoked
values = []
@tm = Rake::Application.new
@tm.define_task(Rake::Task, :z) do values << "top z" end
@tm.in_namespace("a") do
@tm.define_task(Rake::Task, :z) do values << "next z" end
@tm.define_task(Rake::Task, :x => :z)
end
@tm["a:x"].invoke
assert_equal ["next z"], values
end
end
class TestTaskManagerArgumentResolution < Test::Unit::TestCase
def test_good_arg_patterns
assert_equal [:t, [], []], task(:t)
assert_equal [:t, [], [:x]], task(:t => :x)
assert_equal [:t, [], [:x, :y]], task(:t => [:x, :y])
assert_equal [:t, [:a, :b], []], task(:t, :a, :b)
assert_equal [:t, [], [:x]], task(:t, :needs => :x)
assert_equal [:t, [:a, :b], [:x]], task(:t, :a, :b, :needs => :x)
assert_equal [:t, [:a, :b], [:x, :y]], task(:t, :a, :b, :needs => [:x, :y])
assert_equal [:t, [:a, :b], []], task(:t, [:a, :b])
assert_equal [:t, [:a, :b], [:x]], task(:t, [:a, :b] => :x)
assert_equal [:t, [:a, :b], [:x, :y]], task(:t, [:a, :b] => [:x, :y])
end
def task(*args)
tm = TaskManager.new
tm.resolve_args(args)
end
end

10
test/rake/test_tasklib.rb Normal file
View file

@ -0,0 +1,10 @@
require 'test/unit'
require 'rake/tasklib'
class TestTaskLib < Test::Unit::TestCase
def test_paste
tl = Rake::TaskLib.new
assert_equal :ab, tl.paste(:a, :b)
end
end

369
test/rake/test_tasks.rb Normal file
View file

@ -0,0 +1,369 @@
require 'test/unit'
require 'fileutils'
require 'rake'
require_relative 'filecreation'
require_relative 'capture_stdout'
######################################################################
class TestTask < Test::Unit::TestCase
include CaptureStdout
include Rake
def setup
Task.clear
end
def test_create
arg = nil
t = task(:name) { |task| arg = task; 1234 }
assert_equal "name", t.name
assert_equal [], t.prerequisites
assert t.needed?
t.execute(0)
assert_equal t, arg
assert_nil t.source
assert_equal [], t.sources
end
def test_inspect
t = task(:foo, :needs => [:bar, :baz])
assert_equal "<Rake::Task foo => [bar, baz]>", t.inspect
end
def test_invoke
runlist = []
t1 = task(:t1 => [:t2, :t3]) { |t| runlist << t.name; 3321 }
t2 = task(:t2) { |t| runlist << t.name }
t3 = task(:t3) { |t| runlist << t.name }
assert_equal ["t2", "t3"], t1.prerequisites
t1.invoke
assert_equal ["t2", "t3", "t1"], runlist
end
def test_invoke_with_circular_dependencies
runlist = []
t1 = task(:t1 => [:t2]) { |t| runlist << t.name; 3321 }
t2 = task(:t2 => [:t1]) { |t| runlist << t.name }
assert_equal ["t2"], t1.prerequisites
assert_equal ["t1"], t2.prerequisites
ex = assert_raise RuntimeError do
t1.invoke
end
assert_match(/circular dependency/i, ex.message)
assert_match(/t1 => t2 => t1/, ex.message)
end
def test_dry_run_prevents_actions
Rake.application.options.dryrun = true
runlist = []
t1 = task(:t1) { |t| runlist << t.name; 3321 }
out = capture_stdout { t1.invoke }
assert_match(/execute .*t1/i, out)
assert_match(/dry run/i, out)
assert_no_match(/invoke/i, out)
assert_equal [], runlist
ensure
Rake.application.options.dryrun = false
end
def test_tasks_can_be_traced
Rake.application.options.trace = true
t1 = task(:t1)
out = capture_stdout {
t1.invoke
}
assert_match(/invoke t1/i, out)
assert_match(/execute t1/i, out)
ensure
Rake.application.options.trace = false
end
def test_no_double_invoke
runlist = []
t1 = task(:t1 => [:t2, :t3]) { |t| runlist << t.name; 3321 }
t2 = task(:t2 => [:t3]) { |t| runlist << t.name }
t3 = task(:t3) { |t| runlist << t.name }
t1.invoke
assert_equal ["t3", "t2", "t1"], runlist
end
def test_can_double_invoke_with_reenable
runlist = []
t1 = task(:t1) { |t| runlist << t.name }
t1.invoke
t1.reenable
t1.invoke
assert_equal ["t1", "t1"], runlist
end
def test_clear
t = task("t" => "a") { }
t.clear
assert t.prerequisites.empty?, "prerequisites should be empty"
assert t.actions.empty?, "actions should be empty"
end
def test_clear_prerequisites
t = task("t" => ["a", "b"])
assert_equal ['a', 'b'], t.prerequisites
t.clear_prerequisites
assert_equal [], t.prerequisites
end
def test_clear_actions
t = task("t") { }
t.clear_actions
assert t.actions.empty?, "actions should be empty"
end
def test_find
task :tfind
assert_equal "tfind", Task[:tfind].name
ex = assert_raise(RuntimeError) { Task[:leaves] }
assert_equal "Don't know how to build task 'leaves'", ex.message
end
def test_defined
assert ! Task.task_defined?(:a)
task :a
assert Task.task_defined?(:a)
end
def test_multi_invocations
runs = []
p = proc do |t| runs << t.name end
task({:t1=>[:t2,:t3]}, &p)
task({:t2=>[:t3]}, &p)
task(:t3, &p)
Task[:t1].invoke
assert_equal ["t1", "t2", "t3"], runs.sort
end
def test_task_list
task :t2
task :t1 => [:t2]
assert_equal ["t1", "t2"], Task.tasks.collect {|t| t.name}
end
def test_task_gives_name_on_to_s
task :abc
assert_equal "abc", Task[:abc].to_s
end
def test_symbols_can_be_prerequisites
task :a => :b
assert_equal ["b"], Task[:a].prerequisites
end
def test_strings_can_be_prerequisites
task :a => "b"
assert_equal ["b"], Task[:a].prerequisites
end
def test_arrays_can_be_prerequisites
task :a => ["b", "c"]
assert_equal ["b", "c"], Task[:a].prerequisites
end
def test_filelists_can_be_prerequisites
task :a => FileList.new.include("b", "c")
assert_equal ["b", "c"], Task[:a].prerequisites
end
def test_investigation_output
t1 = task(:t1 => [:t2, :t3]) { |t| runlist << t.name; 3321 }
task(:t2)
task(:t3)
out = t1.investigation
assert_match(/class:\s*Rake::Task/, out)
assert_match(/needed:\s*true/, out)
assert_match(/pre-requisites:\s*--t[23]/, out)
end
def test_extended_comments
desc %{
This is a comment.
And this is the extended comment.
name -- Name of task to execute.
rev -- Software revision to use.
}
t = task(:t, :name, :rev)
assert_equal "[name,rev]", t.arg_description
assert_equal "This is a comment.", t.comment
assert_match(/^\s*name -- Name/, t.full_comment)
assert_match(/^\s*rev -- Software/, t.full_comment)
assert_match(/\A\s*This is a comment\.$/, t.full_comment)
end
def test_multiple_comments
desc "line one"
t = task(:t)
desc "line two"
task(:t)
assert_equal "line one / line two", t.comment
end
def test_settable_comments
t = task(:t)
t.comment = "HI"
assert_equal "HI", t.comment
end
end
######################################################################
class TestTaskWithArguments < Test::Unit::TestCase
include CaptureStdout
include Rake
def setup
Task.clear
end
def test_no_args_given
t = task :t
assert_equal [], t.arg_names
end
def test_args_given
t = task :t, :a, :b
assert_equal [:a, :b], t.arg_names
end
def test_name_and_needs
t = task(:t => [:pre])
assert_equal "t", t.name
assert_equal [], t.arg_names
assert_equal ["pre"], t.prerequisites
end
def test_name_and_explicit_needs
t = task(:t, :needs => [:pre])
assert_equal "t", t.name
assert_equal [], t.arg_names
assert_equal ["pre"], t.prerequisites
end
def test_name_args_and_explicit_needs
t = task(:t, :x, :y, :needs => [:pre])
assert_equal "t", t.name
assert_equal [:x, :y], t.arg_names
assert_equal ["pre"], t.prerequisites
end
def test_illegal_keys_in_task_name_hash
assert_raise RuntimeError do
t = task(:t, :x, :y => 1, :needs => [:pre])
end
end
def test_arg_list_is_empty_if_no_args_given
t = task(:t) { |tt, args| assert_equal({}, args.to_hash) }
t.invoke(1, 2, 3)
end
def test_tasks_can_access_arguments_as_hash
t = task :t, :a, :b, :c do |tt, args|
assert_equal({:a => 1, :b => 2, :c => 3}, args.to_hash)
assert_equal 1, args[:a]
assert_equal 2, args[:b]
assert_equal 3, args[:c]
assert_equal 1, args.a
assert_equal 2, args.b
assert_equal 3, args.c
end
t.invoke(1, 2, 3)
end
def test_actions_of_various_arity_are_ok_with_args
notes = []
t = task(:t, :x) do
notes << :a
end
t.enhance do | |
notes << :b
end
t.enhance do |task|
notes << :c
assert_kind_of Task, task
end
t.enhance do |t2, args|
notes << :d
assert_equal t, t2
assert_equal({:x => 1}, args.to_hash)
end
assert_nothing_raised do t.invoke(1) end
assert_equal [:a, :b, :c, :d], notes
end
def test_arguments_are_passed_to_block
t = task(:t, :a, :b) { |tt, args|
assert_equal( { :a => 1, :b => 2 }, args.to_hash )
}
t.invoke(1, 2)
end
def test_extra_parameters_are_ignored
t = task(:t, :a) { |tt, args|
assert_equal 1, args.a
assert_nil args.b
}
t.invoke(1, 2)
end
def test_arguments_are_passed_to_all_blocks
counter = 0
t = task :t, :a
task :t do |tt, args|
assert_equal 1, args.a
counter += 1
end
task :t do |tt, args|
assert_equal 1, args.a
counter += 1
end
t.invoke(1)
assert_equal 2, counter
end
def test_block_with_no_parameters_is_ok
t = task(:t) { }
t.invoke(1, 2)
end
def test_name_with_args
desc "T"
t = task(:tt, :a, :b)
assert_equal "tt", t.name
assert_equal "T", t.comment
assert_equal "[a,b]", t.arg_description
assert_equal "tt[a,b]", t.name_with_args
assert_equal [:a, :b],t.arg_names
end
def test_named_args_are_passed_to_prereqs
value = nil
pre = task(:pre, :rev) { |t, args| value = args.rev }
t = task(:t, :name, :rev, :needs => [:pre])
t.invoke("bill", "1.2")
assert_equal "1.2", value
end
def test_args_not_passed_if_no_prereq_names
pre = task(:pre) { |t, args|
assert_equal({}, args.to_hash)
assert_equal "bill", args.name
}
t = task(:t, :name, :rev, :needs => [:pre])
t.invoke("bill", "1.2")
end
def test_args_not_passed_if_no_arg_names
pre = task(:pre, :rev) { |t, args|
assert_equal({}, args.to_hash)
}
t = task(:t, :needs => [:pre])
t.invoke("bill", "1.2")
end
end

View file

@ -0,0 +1,81 @@
require 'tmpdir'
require 'test/unit'
require 'rake/testtask'
class TestTestTask < Test::Unit::TestCase
include Rake
def setup
@oldwd = Dir.pwd
@tmpwd = Dir.mktmpdir
Dir.chdir(@tmpwd)
Task.clear
ENV.delete('TEST')
open('install.rb', 'w') {}
end
def teardown
FileUtils.rm_rf("testdata")
Dir.chdir(@oldwd)
FileUtils.rm_rf(@tmpwd)
end
def test_no_task
assert ! Task.task_defined?(:test)
end
def test_defaults
tt = Rake::TestTask.new do |t| end
assert_not_nil tt
assert_equal :test, tt.name
assert_equal ['lib'], tt.libs
assert_equal 'test/test*.rb', tt.pattern
assert_equal false, tt.verbose
assert Task.task_defined?(:test)
end
def test_non_defaults
tt = Rake::TestTask.new(:example) do |t|
t.libs = ['src', 'ext']
t.pattern = 'test/tc_*.rb'
t.verbose = true
end
assert_not_nil tt
assert_equal :example, tt.name
assert_equal ['src', 'ext'], tt.libs
assert_equal 'test/tc_*.rb', tt.pattern
assert_equal true, tt.verbose
assert Task.task_defined?(:example)
end
def test_pattern
tt = Rake::TestTask.new do |t|
t.pattern = '*.rb'
end
assert_equal ['install.rb'], tt.file_list.to_a
end
def test_env_test
ENV['TEST'] = 'testfile.rb'
tt = Rake::TestTask.new do |t|
t.pattern = '*'
end
assert_equal ["testfile.rb"], tt.file_list.to_a
end
def test_test_files
tt = Rake::TestTask.new do |t|
t.test_files = FileList['a.rb', 'b.rb']
end
assert_equal ["a.rb", 'b.rb'], tt.file_list.to_a
end
def test_both_pattern_and_test_files
tt = Rake::TestTask.new do |t|
t.test_files = FileList['a.rb', 'b.rb']
t.pattern = '*.rb'
end
assert_equal ['a.rb', 'b.rb', 'install.rb'], tt.file_list.to_a
end
end

View file

@ -0,0 +1,91 @@
require 'test/unit'
require_relative 'capture_stdout'
require 'rake'
class TestTopLevelFunctions < Test::Unit::TestCase
include CaptureStdout
def setup
super
@app = Rake.application
Rake.application = @mock = Object.new
end
def teardown
Rake.application = @app
super
end
def defmock(sym, &block)
class << @mock; self; end.class_eval do
define_method(sym, block)
end
end
def test_namespace
args = []
defmock(:in_namespace) {|a, *| args << a}
namespace "xyz" do end
assert_equal(["xyz"], args)
end
def test_import
args = []
defmock(:add_import) {|a| args << a}
import('x', 'y', 'z')
assert_equal(['x', 'y', 'z'], args)
end
def test_when_writing
out = capture_stdout do
when_writing("NOTWRITING") do
puts "WRITING"
end
end
assert_equal "WRITING\n", out
end
def test_when_not_writing
RakeFileUtils.nowrite_flag = true
out = capture_stdout do
when_writing("NOTWRITING") do
puts "WRITING"
end
end
assert_equal "DRYRUN: NOTWRITING\n", out
ensure
RakeFileUtils.nowrite_flag = false
end
def test_missing_constants_task
args = []
defmock(:const_warning) {|a| args << a}
Object.const_missing(:Task)
assert_equal([:Task], args)
end
def test_missing_constants_file_task
args = []
defmock(:const_warning) {|a| args << a}
Object.const_missing(:FileTask)
assert_equal([:FileTask], args)
end
def test_missing_constants_file_creation_task
args = []
defmock(:const_warning) {|a| args << a}
Object.const_missing(:FileCreationTask)
assert_equal([:FileCreationTask], args)
end
def test_missing_constants_rake_app
args = []
defmock(:const_warning) {|a| args << a}
Object.const_missing(:RakeApp)
assert_equal([:RakeApp], args)
end
def test_missing_other_constant
assert_raise(NameError) do Object.const_missing(:Xyz) end
end
end

68
test/rake/test_win32.rb Normal file
View file

@ -0,0 +1,68 @@
require 'test/unit'
require_relative 'in_environment'
require 'rake'
class TestWin32 < Test::Unit::TestCase
include InEnvironment
Win32 = Rake::Win32
def test_win32_system_dir_uses_home_if_defined
in_environment('RAKE_SYSTEM' => nil, 'HOME' => 'C:\\HP') do
assert_equal "C:/HP/Rake", Win32.win32_system_dir
end
end
def test_win32_system_dir_uses_homedrive_homepath_when_no_home_defined
in_environment(
'RAKE_SYSTEM' => nil,
'HOME' => nil,
'HOMEDRIVE' => "C:",
'HOMEPATH' => "\\HP"
) do
assert_equal "C:/HP/Rake", Win32.win32_system_dir
end
end
def test_win32_system_dir_uses_appdata_when_no_home_or_home_combo
in_environment(
'RAKE_SYSTEM' => nil,
'HOME' => nil,
'HOMEDRIVE' => nil,
'HOMEPATH' => nil,
'APPDATA' => "C:\\Documents and Settings\\HP\\Application Data"
) do
assert_equal "C:/Documents and Settings/HP/Application Data/Rake", Win32.win32_system_dir
end
end
def test_win32_system_dir_fallback_to_userprofile_otherwise
in_environment(
'RAKE_SYSTEM' => nil,
'HOME' => nil,
'HOMEDRIVE' => nil,
'HOMEPATH' => nil,
'APPDATA' => nil,
'USERPROFILE' => "C:\\Documents and Settings\\HP"
) do
assert_equal "C:/Documents and Settings/HP/Rake", Win32.win32_system_dir
end
end
def test_win32_system_dir_nil_of_no_env_vars
in_environment(
'RAKE_SYSTEM' => nil,
'HOME' => nil,
'HOMEDRIVE' => nil,
"HOMEPATH" => nil,
'APPDATA' => nil,
"USERPROFILE" => nil
) do
assert_raise(Rake::Win32::Win32HomeError) do
Win32.win32_system_dir
end
end
end
end if Rake::Win32.windows?