buildr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From as...@apache.org
Subject svn commit: r594720 [9/9] - in /incubator/buildr/trunk: ./ bin/ doc/ doc/css/ doc/images/ doc/pages/ lib/ lib/buildr/ lib/buildr/jetty/ lib/core/ lib/java/ lib/tasks/ test/
Date Tue, 13 Nov 2007 23:44:17 GMT
Added: incubator/buildr/trunk/test/project.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/test/project.rb?rev=594720&view=auto
==============================================================================
--- incubator/buildr/trunk/test/project.rb (added)
+++ incubator/buildr/trunk/test/project.rb Tue Nov 13 15:44:11 2007
@@ -0,0 +1,647 @@
+require File.join(File.dirname(__FILE__), 'sandbox')
+
+
+describe Project do
+  it "should be findable" do
+    foo = define("foo")
+    project("foo").should be(foo)
+  end
+
+  it "should not exist unless defined" do
+    lambda { project("foo") }.should raise_error(RuntimeError, /No such project/)
+  end
+
+  it "should exist once defined" do
+    define "foo"
+    lambda { project("foo") }.should_not raise_error
+  end
+
+  it "should always return same project for same name" do
+    foo, bar = define("foo"), define("bar")
+    foo.should_not be(bar)
+    foo.should be(project("foo"))
+    bar.should be(project("bar"))
+  end
+    
+  it "should show up in projects list if defined" do
+    define("foo")
+    projects.map(&:name).should include("foo")
+  end
+
+  it "should not show up in projects list unless defined" do
+    projects.map(&:name).should_not include("foo")
+  end
+
+  it "should be findable from within a project" do
+    define("foo")
+    project("foo").project("foo").should be(project("foo"))
+  end
+
+  it "should cease to exist when project list cleared" do
+    define "foo"
+    projects.map(&:name).should include("foo")
+    Project.clear
+    projects.map(&:name).should be_empty
+  end
+
+  it "should be defined only once" do
+    lambda { define "foo" }.should_not raise_error
+    lambda { define "foo" }.should raise_error
+  end
+
+  it "should be definable in any order" do
+    Buildr.define("baz") { define("bar") { project("foo:bar") } }
+    Buildr.define("foo") { define("bar") }
+    lambda { project("foo") }.should_not raise_error
+  end
+
+  it "should detect circular dependency" do
+    Buildr.define("baz") { define("bar") { project("foo:bar") } }
+    Buildr.define("foo") { define("bar") { project("baz:bar") } }
+    lambda { project("foo") }.should raise_error(RuntimeError, /Circular dependency/)
+  end
+end
+
+
+describe Project, " name" do
+  it "should be pwd if not specified" do
+    foo = define("foo")
+    foo.base_dir.should eql(Dir.pwd)
+  end
+
+  it "should come from property, if specified" do
+    foo = define("foo", :base_dir=>"tmp")
+    foo.base_dir.should eql(File.expand_path("tmp"))
+  end
+
+  it "should be expanded path" do
+    foo = define("foo", :base_dir=>"tmp")
+    foo.base_dir.should eql(File.expand_path("tmp"))
+  end
+
+  it "should be relative to parent project" do
+    define("foo") { define "bar" }
+    project("foo:bar").base_dir.should eql(File.join(project("foo").base_dir, "bar"))
+  end
+
+  it "should be settable only if not read" do
+    lambda { define("foo", :base_dir=>"tmp") }.should_not raise_error
+    lambda { define("bar", :base_dir=>"tmp") { self.base_dir = "bar" } }.should raise_error(Exception, /Cannot set/)
+  end
+end
+
+
+describe Project, " property" do
+  it "should be set if passed as argument" do
+    define "foo", "version"=>"1.1"
+    project("foo").version.should eql("1.1")
+  end
+
+  it "should be set if assigned in body" do
+    define("foo") { self.version = "1.2" }
+    project("foo").version.should eql("1.2")
+  end
+
+  it "should take precedence when assigned in body" do
+    define("foo", "version"=>"1.1") { self.version = "1.2" }
+    project("foo").version.should eql("1.2")
+  end
+
+  it "should inherit from parent (for some properties)" do
+    define("foo", "version"=>"1.2", :group=>"foobar") { define "bar" }
+    project("foo:bar").version.should eql("1.2")
+    project("foo:bar").group.should eql("foobar")
+  end
+
+  it "should have different value if set in sub-project" do
+    define "foo", "version"=>"1.2", :group=>"foobar" do
+      define "bar", :version=>"1.3" do
+        self.group = "barbaz"
+      end
+    end
+    project("foo:bar").version.should eql("1.3")
+    project("foo:bar").group.should eql("barbaz")
+  end
+end
+
+
+describe Project, " block" do
+  it "should execute once" do
+    define("foo") { self.name.should eql("foo") }
+  end
+
+  it "should execute in describe of project" do
+    define("foo") { self.version = "1.3" }
+    project("foo").version.should eql("1.3")
+  end
+
+  it "should execute by passing project" do
+    define("foo") { |project| project.version = "1.3" }
+    project("foo").version.should eql("1.3")
+  end
+
+  it "should execute in namespace of project" do
+    define("foo") { define("bar") { Rake.application.current_scope.should eql(["foo", "bar"]) } }
+  end
+end
+
+
+describe Project, "#path_to" do
+  before do
+    @project = define("foo") { define("bar") }
+    @base_dir = @project.base_dir
+  end
+
+  it "should return absolute paths as is" do
+    @project.path_to("/tmp").should eql("/tmp")
+  end
+
+  it "should resolve relative paths" do
+    @project.path_to().should eql(@project.base_dir)
+    @project.path_to("tmp").should eql("#{@base_dir}/tmp")
+  end
+
+  it "should accept multiple arguments" do
+    @project.path_to("foo", "bar").should eql("#{@base_dir}/foo/bar")
+  end
+
+  it "should handle relative paths" do
+    @project.path_to("..", "bar").should eql(File.join(@base_dir.pathmap("%d"), "bar"))
+  end
+
+  it "should resolve symbols using accessors" do
+    class << @project
+      def dir ; "foo" ; end
+    end
+    @project.path_to(:dir).should eql(File.join(@base_dir, @project.dir))
+    @project.path_to(:dir, "tmp").should eql(File.join(@base_dir, @project.dir, "tmp"))
+  end
+
+  it "should resolve path for sub-project" do
+    project("foo:bar").path_to("foo").should eql(File.join(project("foo:bar").base_dir, "foo"))
+  end
+end
+
+
+describe Project, "#on_define" do
+  it "should be called when project is defined" do
+    names = []
+    Project.on_define { |project| names << project.name }
+    define "foo" ; define "bar"
+    names.should eql(["foo", "bar"])
+  end
+
+  it "should be called with project object" do
+    Project.on_define { |project| project.name.should eql("foo") }
+    define("foo")
+  end
+
+  it "should be called with project object and set properties" do
+    Project.on_define { |project| project.version.should eql("2.0") }
+    define("foo", :version=>"2.0")
+  end
+
+  it "should execute in namespace of project" do
+    scopes = []
+    Project.on_define { |project| scopes << Rake.application.current_scope }
+    define("foo") { define "bar" }
+    scopes.should eql([["foo"], ["foo", "bar"]])
+  end
+
+  it "should be called before project block" do
+    order = []
+    Project.on_define { |project| order << "on_define" }
+    define("foo") { order << "define" }
+    order.should eql(["on_define", "define"])
+  end
+
+  it "should accept enhancement and call it after project block" do
+    order = []
+    Project.on_define { |project| project.enhance { order << "enhance" } }
+    define("foo") { order << "define" }
+    order.should eql(["define", "enhance"])
+  end
+
+  it "should accept enhancement and call it with project" do
+    Project.on_define { |project| project.enhance { |project| project.name.should eql("foo") } }
+    define("foo")
+  end
+
+  it "should execute enhancement in namespace of project" do
+    scopes = []
+    Project.on_define { |project| project.enhance { scopes << Rake.application.current_scope } }
+    define("foo") { define "bar" }
+    scopes.should eql([["foo"], ["foo", "bar"]])
+  end
+end
+
+
+describe Rake::Task, " recursive" do
+  before do
+    @order = []
+    Project.on_define do |project|
+      project.recursive_task("doda") { @order << project.name }
+    end
+    define("foo") { define("bar") { define("baz") } }
+  end
+
+  it "should invoke same task in child project" do
+    task("foo:doda").invoke
+    @order.should include("foo:bar:baz")
+    @order.should include("foo:bar")
+    @order.should include("foo")
+  end
+
+  it "should invoke in depth-first order" do
+    task("foo:doda").invoke
+    @order.should eql([ "foo:bar:baz", "foo:bar", "foo" ])
+  end
+
+  it "should not invoke task in parent project" do
+    task("foo:bar:baz:doda").invoke
+    @order.should eql([ "foo:bar:baz" ])
+  end
+end
+
+
+describe "Sub-project" do
+  it "should point at parent project" do
+    define("foo") { define "bar" }
+    project("foo:bar").parent.should be(project("foo"))
+  end
+
+  it "should be defined only within parent project" do
+    lambda { define("foo:bar") }.should raise_error
+  end
+
+  it "should have unique name" do
+    lambda do
+      define "foo" do
+        define "bar"
+        define "bar"
+      end 
+    end.should raise_error
+  end
+
+  it "should be findable from root" do
+    define("foo") { define "bar" }
+    projects.map(&:name).should include("foo:bar")
+  end
+
+  it "should be findable from parent project" do
+    define("foo") { define "bar" }
+    project("foo").projects.map(&:name).should include("foo:bar")
+  end
+
+  it "should be findable only if exists" do
+    define("foo") { define "bar" }
+    lambda { project("foo").project("baz") }.should raise_error(RuntimeError, /No such project/)
+  end
+
+  it "should always execute its definition " do
+    ordered = []
+    define "foo" do
+      ordered << self.name
+      define("bar") { ordered << self.name }
+      define("baz") { ordered << self.name }
+    end 
+    ordered.should eql(["foo", "foo:bar", "foo:baz"])
+  end
+
+  it "should execute in order of dependency" do
+    ordered = []
+    define "foo" do
+      ordered << self.name
+      define("bar") { project("foo:baz") ; ordered << self.name }
+      define("baz") { ordered << self.name }
+    end 
+    ordered.should eql(["foo", "foo:baz", "foo:bar"])
+  end
+
+  it "should warn of circular dependency" do
+    lambda do
+      define "foo" do
+        define("bar") { project("foo:baz") }
+        define("baz") { project("foo:bar") }
+      end 
+    end.should raise_error(RuntimeError, /Circular dependency/)
+  end
+end
+
+
+describe "Top-level project" do
+  it "should have no parent" do
+    define("foo")
+    project("foo").parent.should be_nil
+  end
+end
+
+
+describe Buildr, "#project" do
+  it "should raise error if no such project" do
+    lambda { project("foo") }.should raise_error(RuntimeError, /No such project/)
+  end
+
+  it "should return a project if exists" do
+    foo = define("foo")
+    project("foo").should be(foo)
+  end
+
+  it "should find a project by its full name" do
+    bar, baz = nil
+    define("foo") { bar = define("bar") { baz = define("baz")  } }
+    project("foo:bar").should be(bar)
+    project("foo:bar:baz").should be(baz)
+  end
+
+  it "should find a project from any context" do
+    bar, baz = nil
+    define("foo") { bar = define("bar") { baz = define("baz")  } }
+    project("foo:bar").project("foo:bar:baz").should be(baz)
+    project("foo:bar:baz").project("foo:bar").should be(bar)
+  end
+
+  it "should find a project from its parent or sibling project" do
+    define "foo" do
+      define "bar"
+      define "baz"
+    end
+    project("foo").project("bar").should be(project("foo:bar"))
+    project("foo").project("baz").should be(project("foo:baz"))
+    project("foo:bar").project("baz").should be(project("foo:baz"))
+  end
+
+  it "should fine a project from its parent by proximity" do
+    define "foo" do
+      define("bar") { define "baz" }
+      define "baz"
+    end
+    project("foo").project("baz").should be(project("foo:baz"))
+    project("foo:bar").project("baz").should be(project("foo:bar:baz"))
+  end
+
+  it "should invoke project before returning it" do
+    define("foo").should_receive(:invoke).once
+    project("foo")
+  end
+
+  it "should fail if called without a project name" do
+    lambda { project }.should raise_error(ArgumentError)
+  end
+
+  it "should return self if called on a project without a name" do
+    define("foo") { project.should be(self) }
+  end
+
+  it "should evaluate parent project before returning" do
+    # Note: gets around our define that also invokes the project.
+    Buildr.define("foo") { define("bar"); define("baz") }
+    project("foo:bar").should eql(projects[1])
+  end
+end
+
+
+describe Buildr, "#projects" do
+  it "should only return defined projects" do
+    projects.should eql([])
+    define "foo"
+    projects.should eql([project("foo")])
+  end
+
+  it "should return all defined projects" do
+    define "foo"
+    define("bar") { define "baz" }
+    projects.should include(project("foo"))
+    projects.should include(project("bar"))
+    projects.should include(project("bar:baz"))
+  end
+
+  it "should return only named projects" do
+    define "foo" ; define "bar" ; define "baz"
+    projects("foo", "bar").should include(project("foo"))
+    projects("foo", "bar").should include(project("bar"))
+    projects("foo", "bar").should_not include(project("baz"))
+  end
+
+  it "should complain if named project does not exist" do
+    define "foo"
+    projects("foo").should include(project("foo"))
+    lambda { projects("bar") }.should raise_error(RuntimeError, /No such project/)
+  end
+
+  it "should find a project from its parent or sibling project" do
+    define "foo" do
+      define "bar"
+      define "baz"
+    end
+    project("foo").projects("bar").should eql(projects("foo:bar"))
+    project("foo").projects("baz").should eql(projects("foo:baz"))
+    project("foo:bar").projects("baz").should eql(projects("foo:baz"))
+  end
+
+  it "should fine a project from its parent by proximity" do
+    define "foo" do
+      define("bar") { define "baz" }
+      define "baz"
+    end
+    project("foo").projects("baz").should eql(projects("foo:baz"))
+    project("foo:bar").projects("baz").should eql(projects("foo:bar:baz"))
+  end
+
+  it "should evaluate all projects before returning" do
+    # Note: gets around our define that also invokes the project.
+    Buildr.define("foo") { define("bar"); define("baz") }
+    projects.should eql(projects("foo", "foo:bar", "foo:baz"))
+  end
+end
+
+
+describe Rake::Task, " local directory" do
+  before do
+    @task = Project.local_task(task(("doda")))
+    Project.on_define { |project| task("doda") { |task| @task.from project.name } }
+  end
+
+  it "should execute project in local directory" do
+    define "foo"
+    @task.should_receive(:from).with("foo")
+    @task.invoke
+  end
+
+  it "should execute sub-project in local directory" do
+    @task.should_receive(:from).with("foo:bar")
+    define("foo") { define "bar" }
+    in_original_dir(project("foo:bar").base_dir) { @task.invoke }
+  end
+
+  it "should do nothing if no project in local directory" do
+    @task.should_not_receive(:from)
+    define("foo") { define "bar" }
+    in_original_dir("../not_foo") { @task.invoke }
+  end
+
+  it "should find closest project that matches current directory" do
+    mkpath "bar/src/main"
+    define("foo") { define "bar" }
+    @task.should_receive(:from).with("foo:bar")
+    in_original_dir("bar/src/main") { @task.invoke }
+  end
+end
+
+
+describe Project, "#task" do
+  it "should create a regular task" do
+    define("foo") { task("bar") }
+    Rake.application.lookup("foo:bar").should_not be_nil
+  end 
+
+  it "should return a task defined in the project" do
+    define("foo") { task("bar") }
+    project("foo").task("bar").should be_instance_of(Rake::Task)
+  end
+
+  it "should not create task outside project definition" do
+    define "foo"
+    lambda { project("foo").task("bar") }.should raise_error(RuntimeError, /no task foo:bar/)
+  end
+
+  it "should include project name as prefix" do
+    define("foo") { task("bar") }
+    project("foo").task("bar").name.should eql("foo:bar")
+  end
+
+  it "should accept single dependency" do
+    define("foo") { task("bar"=>"baz") }
+    project("foo").task("bar").prerequisites.should include("baz")
+  end
+
+  it "should accept multiple dependencies" do
+    define("foo") { task("bar"=>["baz1", "baz2"]) }
+    project("foo").task("bar").prerequisites.should include("baz1")
+    project("foo").task("bar").prerequisites.should include("baz2")
+  end
+
+  it "should execute task exactly once" do
+    define("foo") do
+      task "baz"
+      task "bar"=>"baz"
+    end
+    lambda { project("foo").task("bar").invoke }.should run_tasks(["foo:baz", "foo:bar"])
+  end
+
+  it "should create a file task" do
+    define("foo") { file("bar") }
+    Rake.application.lookup(File.expand_path("bar")).should_not be_nil
+  end
+
+  it "should create file task with absolute path" do
+    define("foo") { file("/tmp") }
+    Rake.application.lookup("/tmp").should_not be_nil
+  end
+
+  it "should create file task relative to project base directory" do
+    define("foo", :base_dir=>"tmp") { file("bar") }
+    Rake.application.lookup(File.expand_path("tmp/bar")).should_not be_nil
+  end
+
+  it "should accept single dependency" do
+    define("foo") { file("bar"=>"baz") }
+    project("foo").file("bar").prerequisites.should include("baz")
+  end
+
+  it "should accept multiple dependencies" do
+    define("foo") { file("bar"=>["baz1", "baz2"]) }
+    project("foo").file("bar").prerequisites.should include("baz1")
+    project("foo").file("bar").prerequisites.should include("baz2")
+  end
+
+  it "should accept hash arguments" do
+    define("foo") do
+      task "bar"=>"bar_dep"
+      file "baz"=>"baz_dep"
+    end
+    project("foo").task("bar").prerequisites.should include("bar_dep")
+    project("foo").file("baz").prerequisites.should include("baz_dep")
+  end
+
+  it "should return a file task defined in the project" do
+    define("foo") { file("bar") }
+    project("foo").file("bar").should be_instance_of(Rake::FileTask)
+  end
+
+  it "should create file task relative to project definition" do
+    define("foo") { define "bar" }
+    project("foo:bar").file("baz").name.should eql(File.expand_path("bar/baz"))
+  end
+
+  it "should execute task exactly once" do
+    define("foo") do
+      task "baz"
+      file "bar"=>"baz"
+    end
+    lambda { project("foo").file("bar").invoke }.should run_tasks(["foo:baz", project("foo").path_to("bar")])
+  end
+end
+
+
+describe InheritedAttributes do
+  before do
+    class TestAttributes
+      include InheritedAttributes
+      inherited_attr :foo
+      inherited_attr :bar do "barring" end
+      attr_accessor :parent 
+    end
+    @parent = TestAttributes.new
+    @child = TestAttributes.new
+    @child.parent = @parent
+  end
+
+  it "should have getter and setter methods" do
+    @parent.foo = "foo"
+    @parent.bar = "bar"
+    @parent.foo.should eql("foo")
+    @parent.bar.should eql("bar")
+  end
+
+  it "should take default value from block" do
+    @parent.foo.should be_nil
+    @parent.bar.should eql("barring")
+  end
+
+  it "should take default value from parent" do
+    @child.foo.should be_nil
+    @parent.foo = "foo"
+    @child.foo.should eql("foo")
+    @child.foo.should be(@parent.foo)
+  end
+
+  it "should cache default value from parent" do
+    @parent.foo = "foo"
+    @child.foo.should eql("foo")
+    @parent.foo = "bar"
+    @child.foo.should eql("foo")
+  end
+
+  it "should set value in child separately from parent" do
+    @child.bar = "barred"
+    @child.bar.should eql("barred")
+    @parent.bar.should eql("barring")
+  end
+
+  after do
+    Object.send :remove_const, TestAttributes.name
+  end
+end
+
+describe Rake::Task, " buildr:initialize" do
+  it "should be ready to run as the first task" do
+    Rake.application.top_level_tasks.first.should eql("buildr:initialize")
+  end
+
+  it "should evaluate all project definitions" do
+    defined = false
+    Buildr.define("foo") { defined = true }
+    lambda { task("buildr:initialize").invoke }.should change { defined }.to(true)
+  end
+end

Added: incubator/buildr/trunk/test/rake_ext.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/test/rake_ext.rb?rev=594720&view=auto
==============================================================================
--- incubator/buildr/trunk/test/rake_ext.rb (added)
+++ incubator/buildr/trunk/test/rake_ext.rb Tue Nov 13 15:44:11 2007
@@ -0,0 +1,31 @@
+require File.join(File.dirname(__FILE__), 'sandbox')
+
+
+describe "Circular dependency" do
+  it "should raise error for foo=>bar=>foo" do
+    task "foo"=>"bar"
+    task "bar"=>"foo"
+    lambda { task("foo").invoke }.should raise_error(RuntimeError, /foo=>bar=>foo/)
+  end
+
+  it "should raise error for foo=>bar=>baz=>foo" do
+    task "foo"=>"bar"
+    task "bar"=>"baz"
+    task "baz"=>"foo"
+    lambda { task("foo").invoke }.should raise_error(RuntimeError, /foo=>bar=>baz=>foo/)
+  end
+
+  it "should not fail on complex dependencies" do
+    task "foo"=>"bar"
+    task "bar"=>"baz"
+    task "baz"
+    lambda { task("foo").invoke }.should_not raise_error
+  end
+
+  it "should catch circular dependencies in multitask" do
+    multitask "foo"=>["bar", "baz"]
+    task "bar"
+    task "baz"=>"foo"
+    lambda { task("foo").invoke }.should raise_error(RuntimeError, /foo=>baz=>foo/)
+  end
+end

Added: incubator/buildr/trunk/test/sandbox.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/test/sandbox.rb?rev=594720&view=auto
==============================================================================
--- incubator/buildr/trunk/test/sandbox.rb (added)
+++ incubator/buildr/trunk/test/sandbox.rb Tue Nov 13 15:44:11 2007
@@ -0,0 +1,335 @@
+# This file is required twice when running spec test/*.
+unless defined?(Buildr)
+
+  #require "rake"
+  $LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/../lib")
+  require "buildr"
+  #require File.join(File.dirname(__FILE__), "../lib", "buildr.rb")
+
+
+  # The local repository we use for testing is void of any artifacts, which will break given
+  # that the code requires several artifacts. So we establish them first using the real local
+  # repository and cache these across test cases.
+  repositories.remote << "http://repo1.maven.org/maven2"
+  Java.wrapper.load # Anything added to the classpath.
+  artifacts(TestTask::JUNIT_REQUIRES, TestTask::TESTNG_REQUIRES, TestTask::JMOCK_REQUIRES).each { |a| file(a).invoke }
+  task("buildr:initialize").invoke
+
+
+  module Buildr
+
+    module Matchers
+
+      include BuildChecks::Matchers
+
+      module ::Kernel #:nodoc:
+        def warn(message)
+          $warning ||= []
+          $warning << message
+        end
+
+        def warn_deprecated_with_capture(message)
+          verbose(true) { warn_deprecated_without_capture message }
+        end
+        alias_method_chain :warn_deprecated, :capture
+      end
+
+      class WarningMatcher
+        def initialize(message)
+          @expect = message
+        end
+
+        def matches?(target)
+          $warning = []
+          target.call
+          return Regexp === @expect ? $warning.join("\n") =~ @expect : $warning.include?(@expect.to_s)
+        end
+
+        def failure_message()
+          $warning ? "Expected warning #{@expect.source}, found #{$warning}" : "Expected warning #{@expect.source}, no warning issued"
+        end
+      end
+
+      # Tests if a warning was issued. You can use a string or regular expression.
+      #
+      # For example:
+      #   lambda { warn "ze test" }.should warn_that(/ze test/)
+      def warn_that(message)
+        WarningMatcher.new message
+      end
+
+
+      class ::Rake::Task
+        def execute_with_a_record()
+          $executed ||= []
+          $executed << name
+          execute_without_a_record
+        end
+        alias_method_chain :execute, :a_record
+      end
+
+      class InvokeMatcher
+        def initialize(*tasks)
+          @expecting = tasks.map { |task| [task].flatten.map(&:to_s) }
+        end
+
+        def matches?(target)
+          $executed = []
+          target.call
+          return false unless all_ran?
+          return !@but_not.any_ran? if @but_not
+          return true
+        end
+
+        def failure_message()
+          return @but_not.negative_failure_message if all_ran? && @but_not
+          "Expected the tasks #{expected} to run, but #{remaining} did not run, or not in the order we expected them to."
+        end
+
+        def negative_failure_message()
+          if all_ran?
+            "Expected the tasks #{expected} to not run, but they all ran."
+          else
+            "Expected the tasks #{expected} to not run, and all but #{remaining} ran."
+          end 
+        end
+
+        def but_not(*tasks)
+          @but_not = InvokeMatcher.new(*tasks)
+          self
+        end
+
+      protected
+
+        def expected()
+          @expecting.map { |tests| tests.join("=>") }.join(", ")
+        end
+
+        def remaining()
+          @remaining.map { |tests| tests.join("=>") }.join(", ")
+        end
+
+        def all_ran?()
+          @remaining ||= $executed.inject(@expecting) do |expecting, executed|
+            expecting.map { |tasks| tasks.first == executed ? tasks.tail : tasks }.reject(&:empty?)
+          end
+          @remaining.empty?
+        end
+
+        def any_ran?()
+          all_ran?
+          @remaining.size < @expecting.size
+        end
+
+      end
+
+      # Tests that all the tasks ran, in the order specified. Can also be used to test that some
+      # tasks and not others ran.
+      #
+      # Takes a list of arguments. Each argument can be a task name, matching only if that task ran.
+      # Each argument can be an array of task names, matching only if all these tasks ran in that order.
+      # So run_tasks("foo", "bar") expects foo and bar to run in any order, but run_task(["foo", "bar"])
+      # expects foo to run before bar.
+      #
+      # You can call but_not on the matchers to specify that certain tasks must not execute.
+      #
+      # For example:
+      #   # Either task
+      #   lambda { task("compile").invoke }.should run_tasks("compile", "resources")
+      #   # In that order
+      #   lambda { task("build").invoke }.should run_tasks(["compile", "test"])
+      #   # With exclusion
+      #   lambda { task("build").invoke }.should run_tasks("compile").but_not("install")
+      def run_tasks(*tasks)
+        InvokeMatcher.new *tasks
+      end
+
+      # Tests that a task ran. Similar to run_tasks, but accepts a single task name.
+      #
+      # For example:
+      #   lambda { task("build").invoke }.should run_task("test")
+      def run_task(task)
+        InvokeMatcher.new task.to_a.first
+      end
+
+      class UriPathMatcher
+        def initialize(re)
+          @expression = re
+        end
+
+        def matches?(uri)
+          @uri = uri
+          uri.path =~ @expression
+        end
+
+        def description
+          "URI with path matching #{@expression}"
+        end
+      end
+      
+      # Matches a parsed URI's path against the given regular expression
+      def uri(re)
+        UriPathMatcher.new(re)
+      end
+
+    end
+
+
+    module Helpers
+
+      def suppress_stdout()
+        stdout = $stdout
+        $stdout = StringIO.new
+        begin
+          yield
+        ensure
+          $stdout = stdout
+        end
+      end
+
+      def dryrun()
+        Rake.application.options.dryrun = true
+        begin
+          suppress_stdout { yield }
+        ensure
+          Rake.application.options.dryrun = false
+        end
+      end
+
+      # We run tests with tracing off. Then things break. And we need to figure out what went wrong.
+      # So just use trace() as you would use verbose() to find and squash the bug.
+      def trace(value = nil)
+        old_value = Rake.application.options.trace
+        Rake.application.options.trace = value unless value.nil?
+        if block_given?
+          begin
+            yield
+          ensure
+            Rake.application.options.trace = old_value
+          end
+        end
+        Rake.application.options.trace
+      end
+
+      # Change the Rakefile original directory, faking invocation from a different directory.
+      def in_original_dir(dir)
+        begin
+          original_dir = Rake.application.original_dir
+          Rake.application.instance_eval { @original_dir = File.expand_path(dir) }
+          yield
+        ensure
+          Rake.application.instance_eval { @original_dir = original_dir }
+        end 
+      end
+
+
+      # Buildr's define method creates a project definition but does not evaluate it
+      # (that happens once the Rakefile is loaded), and we include Buildr's define in
+      # the test context so we can use it without prefixing with Buildr. This just patches
+      # define to evaluate the project definition before returning it.
+      def define(name, properties = nil, &block) #:yields:project
+        Project.define(name, properties, &block).tap { |project| project.invoke }
+      end
+
+    end
+
+
+    # We need to run all tests inside a sandbox, tacking a snapshot of Rake/Buildr before the test,
+    # and restoring everything to its previous state after the test. Damn state changes.
+    module Sandbox
+
+      def sandbox()
+        @sandbox = {}
+        # During teardown we get rid of all the tasks and start with a clean slate.
+        # Unfortunately, we also get rid of tasks we need, like build, clean, etc.
+        # Here we capture them in their original form, recreated during teardown.
+        @sandbox[:tasks] = Rake.application.tasks.collect do |original|
+          prerequisites = original.prerequisites.clone
+          actions = original.instance_eval { @actions }.clone
+          lambda do
+            original.class.send(:define_task, original.name=>prerequisites).tap do |task|
+              task.comment = original.comment
+              actions.each { |action| task.enhance &action }
+            end
+          end
+        end
+        @sandbox[:rules] = Rake.application.instance_variable_get(:@rules).clone
+
+        # Create a temporary directory where we can create files, e.g,
+        # for projects, compilation. We need a place that does not depend
+        # on the current directory.
+        @test_dir = File.expand_path("tmp", File.dirname(__FILE__))
+        FileUtils.mkpath @test_dir
+        # Move to the work directory and make sure Rake thinks of it as the Rakefile directory.
+        @sandbox[:pwd] = Dir.pwd
+        Dir.chdir @test_dir
+        @sandbox[:original_dir] = Rake.application.original_dir 
+        Rake.application.instance_eval { @original_dir = Dir.pwd }
+        
+        # Later on we'll want to lose all the on_define created during the test.
+        @sandbox[:on_define] = Project.class_eval { @on_define.dup }
+
+        # Create a local repository we can play with. However, our local repository will be void
+        # of some essential artifacts (e.g. JUnit artifacts required by build task), so we create
+        # these first (see above) and keep them across test cases.
+        @sandbox[:artifacts] = Artifact.class_eval { @artifacts }.clone
+        Buildr.repositories.local = File.join(@test_dir, "repository")
+
+        @sandbox[:env_keys] = ENV.keys
+        ["DEBUG", "TEST", "HTTP_PROXY", "USER"].each { |k| ENV.delete(k) ; ENV.delete(k.downcase) }
+
+        # Don't output crap to the console.
+        trace false
+        verbose false
+      end
+
+      # Call this from teardown.
+      def reset()
+        # Remove testing local repository, and reset all repository settings.
+        Buildr.repositories.local = nil
+        Buildr.repositories.remote = nil
+        Buildr.repositories.release_to = nil
+        Buildr.options.proxy.http = nil
+
+        # Get rid of all the projects and the on_define blocks we used.
+        Project.clear
+        on_define = @sandbox[:on_define]
+        Project.class_eval { @on_define = on_define }
+
+        # Switch back Rake directory.
+        Dir.chdir @sandbox[:pwd]
+        original_dir = @sandbox[:original_dir]
+        Rake.application.instance_eval { @original_dir = original_dir }
+        FileUtils.rm_rf @test_dir
+
+        # Get rid of all the tasks and restore the default tasks.
+        Rake::Task.clear
+        @sandbox[:tasks].each { |block| block.call }
+        Rake.application.instance_variable_set :@rules, @sandbox[:rules]
+
+        # Get rid of all artifacts and out test directory.
+        @sandbox[:artifacts].tap { |artifacts| Artifact.class_eval { @artifacts = artifacts } }
+
+        # Restore options.
+        Buildr.options.test = nil
+        (ENV.keys - @sandbox[:env_keys]).each { |key| ENV.delete key }
+      end
+
+    end
+
+  end
+
+  # Allow using matchers within the project definition.
+  class Buildr::Project ; include ::Spec::Matchers, ::Buildr::Matchers ; end
+
+  Spec::Runner.configure do |config|
+    # Make all Buildr methods accessible from test cases, and add various helper methods.
+    config.include Buildr, Buildr::Helpers, Buildr::Matchers
+
+    # Sanbdox Rake/Buildr for each test.
+    config.include Buildr::Sandbox
+    config.before(:each) { sandbox }
+    config.after(:each) { reset }
+  end
+
+end

Added: incubator/buildr/trunk/test/test.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/test/test.rb?rev=594720&view=auto
==============================================================================
--- incubator/buildr/trunk/test/test.rb (added)
+++ incubator/buildr/trunk/test/test.rb Tue Nov 13 15:44:11 2007
@@ -0,0 +1,978 @@
+require File.join(File.dirname(__FILE__), 'sandbox')
+
+
+describe Buildr::TestTask do
+  it "should respond to :prepare and return prepare task" do
+    define("foo") { test.prepare.should be(task("test:prepare")) }
+  end
+
+  it "should respond to :prepare and add prerequisites to test:prepare" do
+    define("foo") { test.prepare "prereq" }
+    project("foo").task("test:prepare").prerequisites.should include("prereq")
+  end
+
+  it "should respond to :prepare and add action for test:prepare" do
+    task "action"
+    define("foo") { test.prepare { task("action").invoke } }
+    lambda { project("foo").test.prepare.invoke }.should run_tasks("action")
+  end
+
+  it "should respond to :compile and return compile task" do
+    define "foo" do
+      test.compile.should be(task("test:compile"))
+      test.compile.should be_kind_of(Buildr::CompileTask)
+    end
+  end
+
+  it "should respond to :compile and add sources to test:compile" do
+    define("foo") { test.compile "prereq" }
+    project("foo").task("test:compile").sources.should include("prereq")
+  end
+
+  it "should respond to :compile and add action for test:compile" do
+    write "src/test/java/Test.java", "class Test {}"
+    task "action"
+    define("foo") { test.compile { task("action").invoke } }
+    lambda { project("foo").test.compile.invoke }.should run_tasks("action")
+  end
+
+  it "should respond to :resources and return resources task" do
+    define "foo" do
+      test.resources.should be(task("test:resources"))
+      test.resources.should be_kind_of(Buildr::ResourcesTask)
+    end
+  end
+
+  it "should respond to :resources and add prerequisites to test:resources" do
+    define("foo") { test.resources "prereq" }
+    project("foo").task("test:resources").prerequisites.should include("prereq")
+  end
+
+  it "should respond to :resources and add action for test:resources" do
+    task "action"
+    define("foo") { test.resources { task("action").invoke } }
+    lambda { project("foo").test.resources.invoke }.should run_tasks("action")
+  end
+
+  it "should respond to :setup and return setup task" do
+    define("foo") { test.setup.should be(task("test:setup")) }
+  end
+
+  it "should respond to :setup and add prerequisites to test:setup" do
+    define("foo") { test.setup "prereq" }
+    project("foo").task("test:setup").prerequisites.should include("prereq")
+  end
+
+  it "should respond to :setup and add action for test:setup" do
+    task "action"
+    define("foo") { test.setup { task("action").invoke } }
+    lambda { project("foo").test.setup.invoke }.should run_tasks("action")
+  end
+
+  it "should respond to :teardown and return teardown task" do
+    define("foo") { test.teardown.should be(task("test:teardown")) }
+  end
+
+  it "should respond to :teardown and add prerequisites to test:teardown" do
+    define("foo") { test.teardown "prereq" }
+    project("foo").task("test:teardown").prerequisites.should include("prereq")
+  end
+
+  it "should respond to :teardown and add action for test:teardown" do
+    task "action"
+    define("foo") { test.teardown { task("action").invoke } }
+    lambda { project("foo").test.teardown.invoke }.should run_tasks("action")
+  end
+
+  it "should respond to :with and return self" do
+    define("foo") { test.with.should be(test) }
+  end
+
+  it "should respond to :with and add artifacfs to compile task classpath" do
+    define("foo") { test.with "test.jar", "acme:example:jar:1.0" }
+    project("foo").test.compile.classpath.should include(File.expand_path("test.jar"))
+    project("foo").test.compile.classpath.should include(artifact("acme:example:jar:1.0"))
+  end
+
+  it "should respond to :with and add artifacfs to task classpath" do
+    define("foo") { test.with "test.jar", "acme:example:jar:1.0" }
+    project("foo").test.classpath.should include(File.expand_path("test.jar"))
+    project("foo").test.classpath.should include(artifact("acme:example:jar:1.0"))
+  end
+
+  it "should respond to :using and return self" do
+    define("foo") { test.using.should be(test) }
+  end
+
+  it "should respond to :using and set value options" do
+    define("foo") { test.using("foo"=>"FOO", "bar"=>"BAR").should be(test) }
+    project("foo").test.options[:foo].should eql("FOO")
+    project("foo").test.options[:bar].should eql("BAR")
+  end
+
+  it "should respond to :using and set symbol options" do
+    define("foo") { test.using(:foo, :bar).should be(test) }
+    project("foo").test.options[:foo].should be_true
+    project("foo").test.options[:bar].should be_true
+  end
+
+  it "should respond to :include and return self" do
+    define("foo") { test.include.should be(test) }
+  end
+
+  it "should respond to :include and add inclusion patterns" do
+    define("foo") { test.include "Foo", "Bar" }
+    project("foo").test.send(:include?, "Foo").should be_true
+    project("foo").test.send(:include?, "Bar").should be_true
+  end
+
+  it "should respond to :exclude and return self" do
+    define("foo") { test.exclude.should be(test) }
+  end
+
+  it "should respond to :exclude and add exclusion patterns" do
+    define("foo") { test.exclude "FooTest", "BarTest" }
+    project("foo").test.send(:include?, "FooTest").should be_false
+    project("foo").test.send(:include?, "BarTest").should be_false
+    project("foo").test.send(:include?, "BazTest").should be_true
+  end
+
+  it "should use JUnit test framework by default" do
+    define "foo"
+    project("foo").test.framework.should eql(:junit)
+  end
+
+  it "should support switching to TestNG framework" do
+    define("foo") { test.using :testng }
+    project("foo").test.framework.should eql(:testng)
+  end
+
+  it "should use the compile classpath" do
+    define("foo") { compile.with "group:id:jar:1.0" }
+    project("foo").test.classpath.should include(artifact("group:id:jar:1.0"))
+  end
+
+  it "should include the compile target in its classpath" do
+    define("foo")
+    project("foo").test.classpath.should include(project("foo").compile.target)
+  end
+
+  it "should clean after itself (test classes)" do
+    define "foo"
+    mkpath project("foo").test.compile.target.to_s
+    lambda { task("clean").invoke }.should change { File.exist?(project("foo").test.compile.target.to_s) }.to(false)
+  end
+
+  it "should clean after itself (reports)" do
+    define "foo"
+    mkpath project("foo").test.report_to.to_s
+    lambda { task("clean").invoke }.should change { File.exist?(project("foo").test.report_to.to_s) }.to(false)
+  end
+
+  it "should pass baseDir property to test case" do
+    define "foo", :base_dir=>"somewhere"
+    project("foo").test.stub!(:classes).and_return ["TestThis"] 
+    project("foo").test.should_receive(:junit_run) do |arg|
+      arg[:properties]["baseDir"].should eql(project("foo").test.compile.target.to_s)
+      []
+    end
+    project("foo").test.invoke
+  end 
+
+  it "should pass environment variables to test case" do
+    define "foo" do
+      test.using :environment=>{ "foo"=>"bar" }
+    end
+    project("foo").test.stub!(:classes).and_return ["TestThis"] 
+    project("foo").test.should_receive(:junit_run) do |arg|
+      arg[:environment]["foo"].should eql("bar")
+      []
+    end
+    project("foo").test.invoke
+  end 
+end
+
+
+describe Buildr::TestTask, " with no tests" do
+  before do
+    define "foo"
+  end
+
+  it "should pass" do
+    lambda { project("foo").test.invoke }.should_not raise_error
+  end
+
+  it "should report no failed tests" do
+    project("foo").test.invoke
+    project("foo").test.failed_tests.should be_empty
+  end
+  
+  it "should report no passed tests" do
+    project("foo").test.invoke
+    project("foo").test.classes.should be_empty
+  end
+
+  it "should execute teardown task" do
+    lambda { project("foo").test.invoke }.should run_task("foo:test:teardown")
+  end
+end
+
+
+describe Buildr::TestTask, " with passing tests" do
+  before do
+    @tests = ["PassingTest1", "PassingTest2"]
+    define "foo"
+    project("foo").test.stub!(:classes).and_return @tests
+    project("foo").test.stub!(:junit_run).and_return []
+  end
+
+  it "should pass" do
+    lambda { project("foo").test.invoke }.should_not raise_error
+  end
+
+  it "should report no failed tests" do
+    project("foo").test.invoke
+    project("foo").test.failed_tests.should be_empty
+  end
+
+  it "should fail if only one test fails" do
+    project("foo").test.stub!(:junit_run).and_return [@tests.last]
+    lambda { project("foo").test.invoke }.should raise_error(RuntimeError, /Tests failed/)
+  end
+
+  it "should execute teardown task" do
+    lambda { project("foo").test.invoke }.should run_task("foo:test:teardown")
+  end
+end
+
+
+describe Buildr::TestTask, " with failed test" do
+  before do
+    @tests = ["FailingTest1", "FailingTest2"]
+    define "foo"
+    project("foo").test.stub!(:classes).and_return @tests
+    project("foo").test.stub!(:junit_run).and_return @tests
+  end
+
+  it "should fail" do
+    lambda { project("foo").test.invoke }.should raise_error(RuntimeError, /Tests failed/)
+  end
+
+  it "should report failed tests" do
+    lambda { verbose(true) { project("foo").test.invoke rescue nil } }.should warn_that(/FailingTest/)
+    project("foo").test.failed_tests.should == @tests
+  end
+
+  it "should warn but not fail if fail_on_failure is false" do
+    project("foo").test.using :fail_on_failure=>false
+    lambda { lambda { verbose(true) { project("foo").test.invoke } }.should_not raise_error }.should warn_that(/FailingTest/)
+    project("foo").test.failed_tests.should == @tests
+  end
+
+  it "should execute teardown task" do
+    lambda { project("foo").test.invoke rescue nil }.should run_task("foo:test:teardown")
+  end
+end
+
+
+describe Buildr::TestTask, " using junit" do
+  before do
+    write "src/test/java/PassingTest.java", 
+      "public class PassingTest extends junit.framework.TestCase { public void testNothing() {} }"
+    write "src/test/java/FailingTest.java", 
+      "public class FailingTest extends junit.framework.TestCase { public void testNothing() { assertTrue(false); } }"
+    define "foo"
+  end
+
+  it "should include JUnit requirements" do
+    project("foo").test.requires.should include(TestTask::JUNIT_REQUIRES)
+    project("foo").test.compile.classpath.should include(artifact(TestTask::JUNIT_REQUIRES))
+    project("foo").test.classpath.should include(artifact(TestTask::JUNIT_REQUIRES))
+  end
+
+  it "should include JMock requirements" do
+    project("foo").test.requires.should include(TestTask::JMOCK_REQUIRES)
+    project("foo").test.compile.classpath.should include(artifact(TestTask::JMOCK_REQUIRES))
+    project("foo").test.classpath.should include(artifact(TestTask::JMOCK_REQUIRES))
+  end
+
+  it "should include classes starting with and ending with Test" do
+    ["TestThis", "ThisTest", "ThisThat"].each do |name|
+      write "target/test-classes/#{name}.class"
+    end
+    project("foo").test.classes.map { |file| File.basename(file) }.should == ["TestThis", "ThisTest"]
+  end
+
+  it "should ignore inner classes" do
+    ["TestThis", "TestThis$Innner"].each do |name|
+      write "target/test-classes/#{name}.class"
+    end
+    project("foo").test.classes.map { |file| File.basename(file) }.should == ["TestThis"]
+  end
+
+  it "should pass when JUnit test case passes" do
+    project("foo").test.include "PassingTest"
+    lambda { project("foo").test.invoke }.should_not raise_error
+  end
+
+  it "should fail when JUnit test case fails" do
+    project("foo").test.include "FailingTest"
+    lambda { project("foo").test.invoke }.should raise_error(RuntimeError, /Tests failed/)
+  end
+
+  it "should report to reports/junit" do
+    project("foo").test.report_to.should be(project("foo").file("reports/junit"))
+    project("foo").test.include("PassingTest").invoke
+    project("foo").file("reports/junit/TEST-PassingTest.txt").should exist
+    project("foo").file("reports/junit/TEST-PassingTest.xml").should exist
+  end
+
+  it "should pass properties to JVM" do
+    write "src/test/java/PropertyTest.java", <<-JAVA
+      public class PropertyTest extends junit.framework.TestCase {
+        public void testProperty() {
+          assertEquals("value", System.getProperty("name"));
+        }
+      }
+    JAVA
+    project("foo").test.include "PropertyTest"
+    project("foo").test.using :properties=>{ 'name'=>'value' }
+    project("foo").test.invoke
+  end
+
+  it "should set current directory" do
+    mkpath "baz"
+    write "baz/src/test/java/CurrentDirectoryTest.java", <<-JAVA
+      public class CurrentDirectoryTest extends junit.framework.TestCase {
+        public void testCurrentDirectory() throws Exception {
+          assertEquals("#{File.expand_path('baz')}", new java.io.File(".").getCanonicalPath());
+        }
+      }
+    JAVA
+    define "bar" do
+      define "baz" do
+        test.include "CurrentDirectoryTest"
+      end
+    end
+    project("bar:baz").test.invoke
+  end
+end
+
+
+describe Buildr::TestTask, " using testng" do
+  before do
+    write "src/test/java/PassingTest.java", 
+      "public class PassingTest { @org.testng.annotations.Test public void testNothing() {} }"
+    write "src/test/java/FailingTest.java", 
+      "public class FailingTest { @org.testng.annotations.Test public void testNothing() { org.testng.AssertJUnit.assertTrue(false); } }"
+    define("foo") { test.using :testng }
+  end
+
+  it "should include TestNG requirements" do
+    project("foo").test.requires.should include(TestTask::TESTNG_REQUIRES)
+    project("foo").test.compile.classpath.should include(artifact(TestTask::TESTNG_REQUIRES))
+    project("foo").test.classpath.should include(artifact(TestTask::TESTNG_REQUIRES))
+  end
+
+  it "should include TestNG requirements" do
+    project("foo").test.requires.should include(TestTask::JMOCK_REQUIRES)
+    project("foo").test.compile.classpath.should include(artifact(TestTask::JMOCK_REQUIRES))
+    project("foo").test.classpath.should include(artifact(TestTask::JMOCK_REQUIRES))
+  end
+
+  it "should include classes starting with and ending with Test" do
+    ["TestThis", "ThisTest", "ThisThat"].each do |name|
+      write File.join(project("foo").test.compile.target.to_s, name).ext("class")
+    end
+    project("foo").test.classes.map { |file| File.basename(file) }.should == ["TestThis", "ThisTest"]
+  end
+
+  it "should ignore inner classes" do
+    ["TestThis", "TestThis$Innner"].each do |name|
+      write "target/test-classes/#{name}.class"
+    end
+    project("foo").test.classes.map { |file| File.basename(file) }.should == ["TestThis"]
+  end
+
+  it "should pass when TestNG test case passes" do
+    project("foo").test.include "PassingTest"
+    lambda { project("foo").test.invoke }.should_not raise_error
+  end
+
+  it "should fail when TestNG test case fails" do
+    project("foo").test.include "FailingTest"
+    lambda { project("foo").test.invoke }.should raise_error(RuntimeError, /Tests failed/)
+  end
+
+  it "should report to reports/testng" do
+    project("foo").test.report_to.should be(project("foo").file("reports/testng"))
+  end
+
+  it "should generate reports" do
+    project("foo").test.include "PassingTest"
+    lambda { project("foo").test.invoke }.should change { File.exist?(project("foo").test.report_to.to_s) }.to(true)
+  end
+end
+
+
+
+describe Buildr::Project.method(:test) do
+  it "should return the project's test task" do
+    define("foo") { test.should be(task("test")) }
+  end
+
+  it "should accept prerequisites for task" do
+    define("foo") { test "prereq" }
+    project("foo").test.prerequisites.should include("prereq")
+  end
+
+  it "should accept actions for task" do
+    task "action"
+    define("foo") { test { task("action").invoke } }
+    lambda { project("foo").test.invoke }.should run_tasks("action")
+  end
+
+  it "should set fail_on_failure by default" do
+    define("foo") { test.options[:fail_on_failure].should be_true }
+  end
+
+  it "should set fork mode by default" do
+    define("foo") { test.options[:fork].should == :once }
+  end
+
+  it "should set no properties by default" do
+    define("foo") { test.options[:properties].should be_empty }
+  end
+
+  it "should set no environment variables by default" do
+    define("foo") { test.options[:environment].should be_empty }
+  end
+
+  it "should inherit options from parent project" do
+    define "foo" do
+      test.using :fail_on_failure=>false, :fork=>:each, :other=>"hello"
+      define "bar" do
+        test.options[:fail_on_failure].should be_false
+        test.options[:fork].should == :each
+        test.options[:other].should == "hello"
+      end
+    end
+  end
+
+  it "should clone options from parent project" do
+    define "foo" do
+      define "bar" do
+        test.using :fail_on_failure=>false, :fork=>:each, :other=>"hello"
+      end.invoke
+      test.options[:fail_on_failure].should be_true
+      test.options[:fork].should == :once
+      test.options[:other].should be_nil
+    end
+  end
+
+  it "should not inherit options from local test task" do
+    class << task("test")
+      def options ; fail ; end
+    end
+    lambda { define("foo") { test.options } }.should_not raise_error
+  end
+end
+
+
+describe Rake::Task, "test" do
+  it "should execute the compile task" do
+    write "src/test/java/Nothing.java", "class Nothing {}"
+    define "foo"
+    lambda { project("foo").test.invoke }.should run_tasks("foo:test:compile")
+  end
+
+  it "should execute the setup task after the compile task" do
+    write "src/test/java/Nothing.java", "class Nothing {}"
+    define "foo"
+    lambda { project("foo").test.invoke }.should run_tasks(["foo:test:compile", "foo:test:setup"])
+  end
+
+  it "should execute all other actions after the setup task" do
+    define "foo" do
+      task "enhanced"
+      test { task("enhanced").invoke }
+    end
+    lambda { project("foo").test.invoke }.should run_tasks(["foo:test:setup", "foo:enhanced"])
+  end
+
+  it "should execute the teardown task after all actions" do
+    define "foo" do
+      task "enhanced"
+      test { task("enhanced").invoke }
+    end
+    lambda { project("foo").test.invoke }.should run_tasks(["foo:enhanced", "foo:test:teardown"])
+  end
+
+  it "should be recursive" do
+    define("foo") { define "bar" }
+    lambda { task("test").invoke }.should run_tasks("foo:test", "foo:bar:test")
+  end
+
+  it "should warn when calling junit" do
+    verbose(true) { lambda { define("foo") { test.junit } }.should warn_that(/deprecated/i) }
+  end
+
+  it "should not execute teardown if setup task failed" do
+    define("foo") { test.setup { fail } }
+    lambda { project("foo").test.invoke rescue nil }.should_not run_task("foo:test:teardown")
+  end
+end
+
+
+describe Buildr::Project, "test:compile" do
+  it "should execute project's compile task first" do
+    write "src/main/java/Nothing.java", "class Nothing {}"
+    write "src/test/java/Test.java", "class Test {}"
+    define "foo"
+    lambda { project("foo").test.compile.invoke }.should run_tasks(["foo:compile", "foo:test:compile"])
+  end
+
+  it "should pick sources from src/test/java if found" do
+    mkpath "src/test/java"
+    define("foo") { test.compile.sources.should eql([_("src/test/java")]) }
+  end
+
+  it "should ignore sources unless they exist" do
+    define("foo") { test.compile.sources.should be_empty }
+  end
+
+  it "should compile to :target/test-classes" do
+    define("foo", :target=>"targeted") { test.compile.target.should eql(file("targeted/test-classes")) }
+  end
+
+  it "should use the compile classpath" do
+    define("foo") { compile.with "group:id:jar:1.0" }
+    project("foo").test.compile.classpath.should include(artifact("group:id:jar:1.0"))
+  end
+
+  it "should include the compiled target in its classpath" do
+    define("foo") { compile.into "odd" }
+    project("foo").test.compile.classpath.should include(project("foo").file("odd"))
+  end
+
+  it "should include the test framework artifacts in its classpath" do
+    define "foo"
+    project("foo").test.compile.classpath.select { |path| path.respond_to?(:to_spec) }.map(&:to_spec).tap do |specs|
+      project("foo").test.requires.each { |spec| specs.should include(spec) }
+    end
+  end
+
+  it "should execute prepare task first" do
+    write "src/test/java/Nothing.java", "class Nothing {}"
+    define "foo"
+    lambda { project("foo").test.compile.invoke }.should run_tasks(["foo:test:prepare", "foo:test:compile"])
+  end
+
+  it "should clean after itself" do
+    write "src/test/java/Nothing.java", "class Nothing {}"
+    define("foo") { test.compile.into "test-compiled" }
+    project("foo").test.compile.invoke
+    lambda { project("foo").clean.invoke }.should change { File.exist?("test-compiled") }.to(false)
+  end
+end
+
+
+describe Buildr::Project, "test:resources" do
+  it "should pick resources from src/test/resources if found" do
+    mkpath "src/test/resources"
+    define("foo") { test.resources.source.should eql(file("src/test/resources")) }
+  end
+
+  it "should ignore resources unless they exist" do
+    define("foo") { test.resources.source.should be_nil }
+  end
+
+  it "should copy to the compile target directory" do
+    define("foo", :target=>"targeted") { test.resources.target.should eql(file("targeted/test-classes")) }
+  end
+
+  it "should execute alongside compile task" do
+    task "action"
+    define("foo") { test.resources { task("action").invoke } }
+    lambda { project("foo").task("test:compile").invoke }.should run_tasks("action")
+  end
+end
+
+
+describe Rake::Task, "test" do
+  it "should be local task" do
+    define "foo"
+    define "bar", :base_dir=>"bar"
+    lambda { task("test").invoke }.should run_task("foo:test").but_not("bar:test")
+  end
+
+  it "should stop at first failure" do
+    define("foo") { test { fail } }
+    define("bar") { test { fail } }
+    lambda { task("test").invoke rescue nil }.should run_tasks("bar:test").but_not("foo:test")
+  end
+
+  it "should ignore failure if options.test is :all" do
+    define("foo") { test { fail } }
+    define("bar") { test { fail } }
+    options.test = :all 
+    lambda { task("test").invoke rescue nil }.should run_tasks("foo:test", "bar:test")
+  end
+
+  it "should ignore failure if options.test is :all" do
+    define("foo") { test { fail } }
+    define("bar") { test { fail } }
+    ENV["test"] = "all"
+    lambda { task("test").invoke rescue nil }.should run_tasks("foo:test", "bar:test")
+  end
+end
+
+describe "test rule" do
+  before do
+    define("foo") { define "bar" }
+  end
+
+  it "should execute test task on local project" do
+    lambda { task("test:something").invoke }.should run_task("foo:test")
+  end
+
+  it "should reset tasks to specific pattern" do
+    task("test:something").invoke
+    ["foo", "foo:bar"].map { |name| project(name) }.each do |project|
+      project.test.include?("something").should be_true
+      project.test.include?("nothing").should be_false
+      project.test.include?("SomeTest").should be_false
+    end
+  end
+
+  it "should apply *name* pattern" do
+    task("test:something").invoke
+    project("foo").test.include?("prefix-something-suffix").should be_true
+    project("foo").test.include?("prefix-nothing-suffix").should be_false
+  end
+
+  it "should not apply *name* pattern if asterisks used" do
+    task("test:*something").invoke
+    project("foo").test.include?("prefix-something").should be_true
+    project("foo").test.include?("prefix-something-suffix").should be_false
+  end
+
+  it "should accept multiple tasks separated by commas" do
+    task("test:foo,bar").invoke
+    project("foo").test.include?("foo").should be_true
+    project("foo").test.include?("bar").should be_true
+    project("foo").test.include?("baz").should be_false
+  end
+
+  it "should execute only the named tasts" do
+    write "src/test/java/TestSomething.java",
+      "public class TestSomething extends junit.framework.TestCase { public void testNothing() {} }"
+    write "src/test/java/TestFails.java", "class TestFails {}"
+    task("test:Something").invoke
+  end
+end
+
+
+describe Rake::Task, "build" do
+  it "should include test task if test option is on" do
+    Buildr.options.test = true
+    lambda { task("build").invoke }.should run_tasks("test")
+  end
+
+  it "should include test task if test option is on" do
+    Buildr.options.test = false
+    lambda { task("build").invoke }.should_not run_task("test")
+  end
+end
+
+
+describe Buildr::Options, "test" do
+  it "should be true by default" do
+    Buildr.options.test.should be_true
+  end
+
+  ["skip", "no", "off", "false"].each do |value|
+    it "should be false if test environment variable is '#{value}'" do
+      lambda { ENV["test"] = value }.should change { Buildr.options.test }.to(false)
+    end
+  end
+
+  ["skip", "no", "off", "false"].each do |value|
+    it "should be false if TEST environment variable is '#{value}'" do
+      lambda { ENV["TEST"] = value }.should change { Buildr.options.test }.to(false)
+    end
+  end
+
+  it "should be :all if test environment variable is all" do
+    lambda { ENV["test"] = "all" }.should change { Buildr.options.test }.to(:all)
+  end
+
+  it "should be :all if TEST environment variable is all" do
+    lambda { ENV["TEST"] = "all" }.should change { Buildr.options.test }.to(:all)
+  end
+
+  it "should be true and warn for any other value" do
+    ENV["TEST"] = "funky"
+    lambda { Buildr.options.test.should be(true) }.should warn_that(/expecting the environment variable/i)
+  end
+end
+
+
+describe Rake::Task, "junit:report" do
+
+  it "should default to the target directory reports/junit" do
+    JUnit.report.target.should eql("reports/junit")
+  end
+
+  it "should generate report into the target directory" do
+    JUnit.report.target = "test-report"
+    lambda { task("junit:report").invoke }.should change { File.exist?(JUnit.report.target) }.to(true)
+  end
+
+  it "should clean after itself" do
+    mkpath JUnit.report.target
+    lambda { task("clean").invoke }.should change { File.exist?(JUnit.report.target) }.to(false)
+  end
+
+  it "should generate a consolidated XML report" do
+    lambda { task("junit:report").invoke }.should change { File.exist?("reports/junit/TESTS-TestSuites.xml") }.to(true)
+  end
+
+  it "should default to generating a report with frames" do
+    JUnit.report.frames.should be_true
+  end
+
+  it "should generate single page when frames is false" do
+    JUnit.report.frames = false
+    task("junit:report").invoke
+    file("reports/junit/html/junit-noframes.html").should exist
+  end
+
+  it "should generate frame page when frames is false" do
+    JUnit.report.frames = true
+    task("junit:report").invoke
+    file("reports/junit/html/index.html").should exist
+  end
+
+  it "should generate reports from all projects that ran test cases" do
+    write "src/test/java/TestSomething.java",
+      "public class TestSomething extends junit.framework.TestCase { public void testNothing() {} }"
+    define "foo"
+    project("foo").test.invoke
+    task("junit:report").invoke
+    FileList["reports/junit/html/*TestSomething.html"].size.should be(1)
+  end
+
+  after do
+    JUnit.instance_eval { @report = nil }
+  end
+end
+
+
+describe Buildr, "integration" do
+  it "should return the same task from all contexts" do
+    task = integration
+    define "foo" do
+      integration.should be(task)
+      define "bar" do
+        integration.should be(task)
+      end
+    end
+    integration.should be(task)
+  end
+
+  it "should respond to :setup and return setup task" do
+    setup = integration.setup
+    define("foo") { integration.setup.should be(setup) }
+  end
+
+  it "should respond to :setup and add prerequisites to integration:setup" do
+    define("foo") { integration.setup "prereq" }
+    integration.setup.prerequisites.should include("prereq")
+  end
+
+  it "should respond to :setup and add action for integration:setup" do
+    action = task("action")
+    define("foo") { integration.setup { action.invoke } }
+    lambda { integration.setup.invoke }.should run_tasks(action)
+  end
+
+  it "should respond to :teardown and return teardown task" do
+    teardown = integration.teardown
+    define("foo") { integration.teardown.should be(teardown) }
+  end
+
+  it "should respond to :teardown and add prerequisites to integration:teardown" do
+    define("foo") { integration.teardown "prereq" }
+    integration.teardown.prerequisites.should include("prereq")
+  end
+
+  it "should respond to :teardown and add action for integration:teardown" do
+    action = task("action")
+    define("foo") { integration.teardown { action.invoke } }
+    lambda { integration.teardown.invoke }.should run_tasks(action)
+  end
+end
+
+
+describe Rake::Task, "integration" do
+  it "should be a local task" do
+    define("foo") { test.using :integration }
+    define("bar", :base_dir=>"other") { test.using :integration }
+    lambda { task("integration").invoke }.should run_task("foo:test").but_not("bar:test")
+  end
+
+  it "should be a recursive task" do
+    define "foo" do
+      test.using :integration
+      define("bar") { test.using :integration }
+    end
+    lambda { task("integration").invoke }.should run_tasks("foo:test", "foo:bar:test")
+  end
+
+  it "should find nested integration tests" do
+    define "foo" do
+      define("bar") { test.using :integration }
+    end
+    lambda { task("integration").invoke }.should run_tasks("foo:bar:test").but_not("foo:test")
+  end
+
+  it "should ignore nested regular tasks" do
+    define "foo" do
+      test.using :integration
+      define("bar") { test.using :integration=>false }
+    end
+    lambda { task("integration").invoke }.should run_tasks("foo:test").but_not("foo:bar:test")
+  end
+
+  it "should agree not to run the same tasks as test" do
+    define "foo" do
+      define "bar" do
+        test.using :integration
+        define("baz") { test.using :integration=>false }
+      end
+    end
+    lambda { task("test").invoke }.should run_tasks("foo:test", "foo:bar:baz:test").but_not("foo:bar:test")
+    lambda { task("integration").invoke }.should run_tasks("foo:bar:test").but_not("foo:test", "foo:bar:baz:test")
+  end
+
+  it "should run setup task before any project integration tests" do
+    define("foo") { test.using :integration }
+    define("bar") { test.using :integration }
+    lambda { task("integration").invoke }.should run_tasks([integration.setup, "bar:test", "foo:test"])
+  end
+
+  it "should run teardown task after all project integrations tests" do
+    define("foo") { test.using :integration }
+    define("bar") { test.using :integration }
+    lambda { task("integration").invoke }.should run_tasks(["bar:test", "foo:test", integration.teardown])
+  end
+
+  it "should run test cases marked for integration" do
+    write "src/test/java/FailingTest.java", 
+      "public class FailingTest extends junit.framework.TestCase { public void testNothing() { assertTrue(false); } }"
+    define("foo") { test.using :integration }
+    lambda { task("test").invoke }.should_not raise_error
+    lambda { task("integration").invoke }.should raise_error(RuntimeError, /tests failed/i)
+  end
+
+  it "should run setup and teardown tasks marked for integration" do
+    define("foo") { test.using :integration }
+    lambda { task("test").invoke }.should run_tasks().but_not("foo:test:setup", "foo:test:teardown")
+    lambda { task("integration").invoke }.should run_tasks("foo:test:setup", "foo:test:teardown")
+  end
+
+  it "should run test actions marked for integration" do
+    task "action"
+    define "foo" do
+      test.using :integration
+      test { task("action").invoke }
+    end
+    lambda { task("test").invoke }.should run_tasks().but_not("action")
+    lambda { task("integration").invoke }.should run_task("action")
+  end
+
+  it "should not fail if test=all" do
+    write "src/test/java/FailingTest.java", 
+      "public class FailingTest extends junit.framework.TestCase { public void testNothing() { assertTrue(false); } }"
+    define("foo") { test.using :integration }
+    options.test = :all
+    lambda { task("integration").invoke }.should_not raise_error
+  end
+
+  it "should execute by local package task" do
+    define "foo", :version=>"1.0" do
+      test.using :integration
+      package :jar
+    end
+    lambda { task("package").invoke }.should run_tasks(["foo:package", "foo:test"])
+  end
+
+  it "should execute by local package task along with unit tests" do
+    define "foo", :version=>"1.0" do
+      test.using :integration
+      package :jar
+      define("bar") { test.using :integration=>false }
+    end
+    lambda { task("package").invoke }.should run_tasks(["foo:package", "foo:test"],
+      ["foo:bar:build", "foo:bar:test", "foo:bar:package"])
+  end
+
+  it "should not execute by local package task if test=no" do
+    define "foo", :version=>"1.0" do
+      test.using :integration
+      package :jar
+    end
+    options.test = false
+    lambda { task("package").invoke }.should run_task("foo:package").but_not("foo:test")
+  end
+end
+
+
+describe "integration rule" do
+  before do
+    define "foo" do
+      test.using :integration
+      define "bar"
+    end
+  end
+
+  it "should execute integration tests on local project" do
+    lambda { task("integration:something").invoke }.should run_task("foo:test")
+  end
+
+  it "should reset tasks to specific pattern" do
+    task("integration:something").invoke
+    ["foo", "foo:bar"].map { |name| project(name) }.each do |project|
+      project.test.include?("something").should be_true
+      project.test.include?("nothing").should be_false
+      project.test.include?("SomeTest").should be_false
+    end
+  end
+
+  it "should apply *name* pattern" do
+    task("integration:something").invoke
+    project("foo").test.include?("prefix-something-suffix").should be_true
+    project("foo").test.include?("prefix-nothing-suffix").should be_false
+  end
+
+  it "should not apply *name* pattern if asterisks used" do
+    task("integration:*something").invoke
+    project("foo").test.include?("prefix-something").should be_true
+    project("foo").test.include?("prefix-something-suffix").should be_false
+  end
+
+  it "should accept multiple tasks separated by commas" do
+    task("integration:foo,bar").invoke
+    project("foo").test.include?("foo").should be_true
+    project("foo").test.include?("bar").should be_true
+    project("foo").test.include?("baz").should be_false
+  end
+
+  it "should execute only the named tasts" do
+    write "src/test/java/TestSomething.java",
+      "public class TestSomething extends junit.framework.TestCase { public void testNothing() {} }"
+    write "src/test/java/TestFails.java", "class TestFails {}"
+    task("integration:Something").invoke
+  end
+end

Added: incubator/buildr/trunk/test/transport.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/test/transport.rb?rev=594720&view=auto
==============================================================================
--- incubator/buildr/trunk/test/transport.rb (added)
+++ incubator/buildr/trunk/test/transport.rb Tue Nov 13 15:44:11 2007
@@ -0,0 +1,267 @@
+require File.join(File.dirname(__FILE__), 'sandbox')
+
+
+describe URI, "#download" do
+  before do
+    write @source = "source", @content = "Just a file"
+    @uri = URI("file://#{File.expand_path(@source)}")
+    @target = "target"
+  end
+
+  it "should download file if found" do
+    @uri.download @target
+    file(@target).should contain(@content)
+  end
+
+  it "should fail if file not found" do
+    lambda { (@uri + "missing").download @target }.should raise_error(URI::NotFoundError)
+    file(@target).should_not exist
+  end
+
+  it "should work the same way from static method with URI" do
+    URI.download @uri, @target
+    file(@target).should contain(@content)
+  end
+
+  it "should work the same way from static method with String" do
+    URI.download @uri.to_s, @target
+    file(@target).should contain(@content)
+  end
+
+  it "should download to a task" do
+    @uri.download file(@target)
+    file(@target).should contain(@content)
+  end
+
+  it "should download to a file" do
+    File.open(@target, "w") { |file| @uri.download file }
+    file(@target).should contain(@content)
+  end
+end
+
+
+describe URI, "#upload" do
+  before do
+    write @source = "source", @content = "Just a file"
+    @target = "target"
+    @uri = URI("file://#{File.expand_path(@target)}")
+  end
+
+  it "should upload file if found" do
+    @uri.upload @source
+    file(@target).should contain(@content)
+  end
+
+  it "should fail if file not found" do
+    lambda { @uri.upload @source.ext("missing") }.should raise_error(URI::NotFoundError)
+    file(@target).should_not exist
+  end
+
+  it "should work the same way from static method with URI" do
+    URI.upload @uri, @source
+    file(@target).should contain(@content)
+  end
+
+  it "should work the same way from static method with String" do
+    URI.upload @uri.to_s, @source
+    file(@target).should contain(@content)
+  end
+
+  it "should upload from a task" do
+    @uri.upload file(@source)
+    file(@target).should contain(@content)
+  end
+
+  it "should create MD5 hash" do
+    @uri.upload file(@source)
+    file(@target.ext(".md5")).should contain(Digest::MD5.hexdigest(@content))
+  end
+
+  it "should create SHA1 hash" do
+    @uri.upload file(@source)
+    file(@target.ext(".sha1")).should contain(Digest::SHA1.hexdigest(@content))
+  end
+
+  it "should upload an entire directory" do
+    mkpath "dir" ; write "dir/test", "in directory"
+    mkpath "dir/nested" ; write "dir/nested/test", "in nested directory"
+    @uri.upload "dir"
+    file(@target).should contain("test", "nested/test")
+    file(@target + "/test").should contain("in directory")
+    file(@target + "/nested/test").should contain("in nested directory")
+  end
+end
+
+
+describe URI::FILE do
+  it "should complain about file:" do
+    lambda { URI("file:") }.should raise_error(URI::InvalidURIError)
+  end
+
+  it "should accept file:something as file:///something" do
+    URI("file:something").should eql(URI("file:///something"))
+  end
+
+  it "should accept file:/ as file:///" do
+    URI("file:/").should eql(URI("file:///"))
+  end
+
+  it "should accept file:/something as file:///something" do
+    URI("file:/something").should eql(URI("file:///something"))
+  end
+
+  it "should complain about file://" do
+    lambda { URI("file://").should eql(URI("file:///")) }.should raise_error(URI::InvalidURIError)
+  end
+
+  it "should accept file://something as file://something/" do
+    URI("file://something").should eql(URI("file://something/"))
+  end
+
+  it "should accept file:///something" do
+    URI("file:///something").should be_kind_of(URI::FILE)
+    URI("file:///something").to_s.should eql("file:///something")
+    URI("file:///something").path.should eql("/something")
+  end
+
+  it "should treat host as path when host name is a Windows drive" do
+    URI("file://c:/something").should eql(URI("file:///c:/something"))
+  end
+end
+
+
+describe URI::FILE, "#read" do
+  before do
+    @filename = "readme"
+    @uri = URI("file:///#{File.expand_path(@filename)}")
+    @content = "Readme. Please!"
+    write "readme", @content
+  end
+
+  it "should not complain about excessive options" do
+    @uri.read :proxy=>[], :lovely=>true
+  end
+
+  it "should read the file" do
+    @uri.read.should eql(@content)
+  end
+
+  it "should read the file and yield to block" do
+    @uri.read { |content| content.should eql(@content) }
+  end
+
+  it "should raise NotFoundError if file doesn't exist" do
+    lambda { (@uri + "notme").read }.should raise_error(URI::NotFoundError)
+  end
+
+  it "should raise NotFoundError if file is actually a directory" do
+    mkpath "dir"
+    lambda { (@uri + "dir").read }.should raise_error(URI::NotFoundError)
+  end
+end
+
+
+describe URI::FILE, "#write" do
+  before do
+    @filename = "readme"
+    @uri = URI("file:///#{File.expand_path(@filename)}")
+    @content = "Readme. Please!"
+  end
+
+  it "should not complain about excessive options" do
+    @uri.write @content, :proxy=>[], :lovely=>true
+  end
+
+  it "should write the file from a string" do
+    @uri.write @content
+    read(@filename).should eql(@content)
+  end
+
+  it "should write the file from a reader" do
+    reader = Object.new
+    class << reader
+      def read(bytes) ; @array.pop ; end
+    end
+    reader.instance_variable_set :@array, [@content]
+    @uri.write reader
+    read(@filename).should eql(@content)
+  end
+
+  it "should write the file from a block" do
+    array = [@content]
+    @uri.write { array.pop }
+    read(@filename).should eql(@content)
+  end
+
+  it "should not create file if read fails" do
+    @uri.write { fail } rescue nil
+    file(@filename).should_not exist
+  end
+end
+
+
+
+describe URI::HTTP, "#read" do
+  before do
+    @proxy = "http://john:smith@myproxy:8080"
+    @domain = "domain"
+    @host_domain = "host.#{@domain}"
+    @uri = URI("http://#{@host_domain}")
+    @no_proxy_args = [@host_domain, 80]
+    @proxy_args = @no_proxy_args + ["myproxy", 8080, "john", "smith"]
+  end
+
+  it "should not use proxy unless proxy is set" do
+    Net::HTTP.should_receive(:start).with(*@no_proxy_args)
+    @uri.read
+  end
+
+  it "should use proxy from environment variable HTTP_PROXY" do
+    ENV["HTTP_PROXY"] = @proxy
+    Net::HTTP.should_receive(:start).with(*@proxy_args)
+    @uri.read
+  end
+
+  it "should not use proxy for hosts from environment variable NO_PROXY" do
+    ENV["HTTP_PROXY"] = @proxy
+    ENV["NO_PROXY"] = @host_domain
+    Net::HTTP.should_receive(:start).with(*@no_proxy_args)
+    @uri.read
+  end
+
+  it "should use proxy for hosts other than those specified by NO_PROXY" do
+    ENV["HTTP_PROXY"] = @proxy
+    ENV["NO_PROXY"] = "whatever"
+    Net::HTTP.should_receive(:start).with(*@proxy_args)
+    @uri.read
+  end
+
+  it "should support comma separated list in environment variable NO_PROXY" do
+    ENV["HTTP_PROXY"] = @proxy
+    ENV["NO_PROXY"] = "optimus,prime"
+    Net::HTTP.should_receive(:start).with("optimus", 80)
+    URI("http://optimus").read
+    Net::HTTP.should_receive(:start).with("prime", 80)
+    URI("http://prime").read
+    Net::HTTP.should_receive(:start).with("bumblebee", *@proxy_args.tail)
+    URI("http://bumblebee").read
+  end
+
+  it "should support glob pattern in NO_PROXY" do
+    ENV["HTTP_PROXY"] = @proxy
+    ENV["NO_PROXY"] = "*.#{@domain}"
+    Net::HTTP.should_receive(:start).once.with(*@no_proxy_args)
+    @uri.read
+  end
+
+  it "should support specific port in NO_PROXY" do
+    ENV["HTTP_PROXY"] = @proxy
+    ENV["NO_PROXY"] = "#{@host_domain}:80"
+    Net::HTTP.should_receive(:start).with(*@no_proxy_args)
+    @uri.read
+    ENV["NO_PROXY"] = "#{@host_domain}:800"
+    Net::HTTP.should_receive(:start).with(*@proxy_args)
+    @uri.read
+  end
+
+end



Mime
View raw message