[jruby~main:f25167ae] Ant integration: Get _element working better
- From: nicksieger@kenai.com
- To: commits@jruby.kenai.com
- Subject: [jruby~main:f25167ae] Ant integration: Get _element working better
- Date: Thu, 4 Mar 2010 23:08:00 +0000
Project: jruby
Repository: main
Revision: f25167ae6afa7afcebdcdd8d110b320cdd8f851e
Author: nicksieger
Date: 2010-03-04 22:57:05 UTC
Link:
Log Message:
------------
Ant integration: Get _element working better
- Start of a test suite
-- Need more target/task examples - they can go in task_spec.rb
- Also move all Ant elements to be imported/live inside the Ant class
namespace
Revisions:
----------
f25167ae6afa7afcebdcdd8d110b320cdd8f851e
Modified Paths:
---------------
lib/ruby/site_ruby/shared/ant/ant.rb
lib/ruby/site_ruby/shared/ant/element.rb
lib/ruby/site_ruby/shared/ant/target.rb
Added Paths:
------------
spec/java_integration/ant/ant_spec.rb
spec/java_integration/ant/project_spec.rb
spec/java_integration/ant/target_spec.rb
spec/java_integration/ant/task_spec.rb
spec/java_integration/ant_spec_helper.rb
Diffs:
------
diff --git a/lib/ruby/site_ruby/shared/ant/ant.rb
b/lib/ruby/site_ruby/shared/ant/ant.rb
index c2c43e2..e4a4b36 100644
--- a/lib/ruby/site_ruby/shared/ant/ant.rb
+++ b/lib/ruby/site_ruby/shared/ant/ant.rb
@@ -2,52 +2,34 @@ require 'java'
require 'ant/element'
require 'ant/target'
-java_import org.apache.tools.ant.ComponentHelper
-java_import org.apache.tools.ant.DefaultLogger
-java_import org.apache.tools.ant.Location
-java_import org.apache.tools.ant.Project
-java_import org.apache.tools.ant.ProjectHelper
-java_import org.apache.tools.ant.Target
-
class Ant
+ java_import org.apache.tools.ant.ComponentHelper
+ java_import org.apache.tools.ant.DefaultLogger
+ java_import org.apache.tools.ant.Location
+ java_import org.apache.tools.ant.Project
+ java_import org.apache.tools.ant.ProjectHelper
+
attr_reader :project, :log, :location
attr_accessor :current_target
def initialize(options={}, &block)
@options = options
- @location = Location.new(caller.detect{|el| el !~
/^#{__FILE__}/}.split(/:/).first)
+ @location = Ant.location_from_caller
@project = create_project options
@current_target = nil
initialize_elements
- handle_argv unless options[:run] == false || Ant.run ||
@location.file_name != $0
- end
-
- def create_project(options)
- # If we are calling into a rakefile from ant then we already have a
project to use
- return $project if defined?($project) && $project
-
- output_level = options.delete(:output_level) || 2
-
- Project.new.tap do |p|
- p.init
- p.add_build_listener(DefaultLogger.new.tap do |log|
- log.output_print_stream = java.lang.System.out
- log.error_print_stream = java.lang.System.err
- log.emacs_mode = true
- log.message_output_level = output_level
- @log = log
- end)
- helper = ProjectHelper.getProjectHelper
- helper.import_stack.add(Object.new)
- p.addReference(ProjectHelper::PROJECTHELPER_REFERENCE, helper)
- options.each_pair {|k,v| p.send("set_#{k}", v) }
- end
+ process_arguments unless options[:run] == false || Ant.run ||
@location.file_name != $0
+ define_tasks(&block)
end
def properties
@project.properties
end
+ def define_tasks(&code)
+ code.arity == 1 ? code[self] : instance_eval(&code) if code
+ end
+
# Add a target (two forms)
# 1. Execute a block as a target: add_target "foo-target" { echo :message
=> "I am cool" }
# 2. Execute a rake task as a target: add_target
Rake.application["default"]
@@ -58,7 +40,7 @@ class Ant
alias target add_target
def [](name)
- if @project.targets.containsKey(name)
+ if @project.targets.containsKey(name.to_s)
TargetWrapper.new(@project, name)
else
MissingWrapper.new(@project, name)
@@ -109,10 +91,14 @@ class Ant
@elements[name + clazz.to_s] = Element.new(self, name, clazz)
end
- def _element(name, *args, &block)
-# raise "unknown element #{name}!" unless @helper.get_definition(name)
- element = acquire_element(name, nil)
- element.call(@current_target, *args, &block)
+ def _element(name, args = {}, &block)
+ definition = @helper.get_definition(name)
+ clazz = definition.getTypeClass(@project) if definition
+ Element.new(self, name, clazz).call(@current_target, args, &block)
+ end
+
+ def method_missing(name, *args, &block)
+ _element(name, *args, &block)
end
def run(*targets)
@@ -123,18 +109,7 @@ class Ant
end
end
- private
- def generate_children(collection)
- collection.each do |name, clazz|
- element = acquire_element(name, clazz)
- self.class.send(:define_method, Ant.safe_method_name(name)) do |*a, &b|
- element.call(@current_target, *a, &b)
- end
- end
- end
-
- def handle_argv
- argv = ARGV
+ def process_arguments(argv = ARGV, run_at_exit = true)
properties = []
targets = []
argv.each {|a| a =~ /^-D/ ? properties << a[2..-1] : targets << a }
@@ -150,6 +125,39 @@ class Ant
warn e.message
exit 1
end
+ end if run_at_exit
+ end
+
+ private
+ def create_project(options)
+ # If we are calling into a rakefile from ant then we already have a
project to use
+ return $project if defined?($project) && $project
+
+ options[:basedir] ||= '.'
+ output_level = options.delete(:output_level) || 2
+
+ Project.new.tap do |p|
+ p.init
+ p.add_build_listener(DefaultLogger.new.tap do |log|
+ log.output_print_stream = Java::java.lang.System.out
+ log.error_print_stream = Java::java.lang.System.err
+ log.emacs_mode = true
+ log.message_output_level = output_level
+ @log = log
+ end)
+ helper = ProjectHelper.getProjectHelper
+ helper.import_stack.add(Java::java.io.File.new(@location.file_name))
+ p.addReference(ProjectHelper::PROJECTHELPER_REFERENCE, helper)
+ options.each_pair {|k,v| p.send("set_#{k}", v) if
p.respond_to?("set_#{k}") }
+ end
+ end
+
+ def generate_children(collection)
+ collection.each do |name, clazz|
+ element = acquire_element(name, clazz)
+ self.class.send(:define_method, Ant.safe_method_name(name)) do |*a, &b|
+ element.call(@current_target, *a, &b)
+ end
end
end
@@ -164,15 +172,23 @@ class Ant
end
end
+ def location_from_caller
+ file, line = caller.detect{|el| el !~
/^#{File.dirname(__FILE__)}/}.split(/:/)
+ Location.new(file, line.to_i, 1)
+ end
+
def ant(options={}, &code)
if options.respond_to? :to_hash
@ant ||= Ant.new options.to_hash
- code.arity==1 ? code[@ant] : @ant.instance_eval(&code) if
block_given?
+ @ant.define_tasks(&code)
@ant
else
options = options.join(" ") if options.respond_to? :to_ary
sh "ant #{options.to_s}" # FIXME: Make this more secure if using
array form
end
+ rescue => e
+ warn e.message
+ warn e.backtrace.join("\n")
end
end
end
diff --git a/lib/ruby/site_ruby/shared/ant/element.rb
b/lib/ruby/site_ruby/shared/ant/element.rb
index e6a2354..ceb25ce 100644
--- a/lib/ruby/site_ruby/shared/ant/element.rb
+++ b/lib/ruby/site_ruby/shared/ant/element.rb
@@ -1,71 +1,85 @@
require 'java'
-java_import org.apache.tools.ant.IntrospectionHelper
-java_import org.apache.tools.ant.RuntimeConfigurable
-java_import org.apache.tools.ant.UnknownElement
+class Ant
+ java_import org.apache.tools.ant.IntrospectionHelper
+ java_import org.apache.tools.ant.RuntimeConfigurable
+ java_import org.apache.tools.ant.UnknownElement
-# This is really the metadata of the element coupled with the logic for
-# instantiating an instance of an element and evaluating it. My intention
-# is to decouple these two pieces. This has extra value since we can then
-# also make two types of instances for both top-level tasks and for targets
-# since we have some conditionals which would then be eliminated
-class Element
- attr_reader :name
+ class UnknownElement
+ attr_accessor :ant
+ # undef some method names that might collide with ant task/type names
+ %w(test fail abort raise exec trap).each {|m| undef_method(m)}
+ Object.instance_methods.grep(/java/).each {|m| undef_method(m)}
- def initialize(ant, name, clazz)
- @ant, @name, @clazz = ant, name, clazz
- end
+ def _element(name, args = {}, &block)
+ Element.new(ant, name).call(self, args, &block)
+ end
- def call(parent, args={}, &code)
- element = create parent
- assign_attributes element, args
- define_nested_elements element
- code.arity==1 ? code[element] : element.instance_eval(&code) if
block_given?
- if parent.respond_to? :add_task # Target
- @ant.project.log "Adding #{name} to #{parent}", 5
- parent.add_task element
- elsif parent.respond_to? :get_owning_target # Task
- @ant.project.log "Adding #{name} to #{parent.component_name}", 5
- parent.add_child element
- parent.runtime_configurable_wrapper.add_child
element.runtime_configurable_wrapper
- else # Just run it now
- @ant.project.log "Executing #{name}", 5
- element.owning_target = Target.new.tap {|t| t.name = ""}
- element.maybe_configure
- element.execute
+ def method_missing(name, *args, &block)
+ _element(name, *args, &block)
end
end
- private
- def create(parent) # See ProjectHelper2.ElementHelper
- UnknownElement.new(@name).tap do |e|
- e.project = @ant.project
- e.task_name = @name
- e.location = @ant.location
- e.owning_target = @ant.current_target
+ # This is really the metadata of the element coupled with the logic for
+ # instantiating an instance of an element and evaluating it. My intention
+ # is to decouple these two pieces. This has extra value since we can then
+ # also make two types of instances for both top-level tasks and for targets
+ # since we have some conditionals which would then be eliminated
+ class Element
+ attr_reader :name
+
+ def initialize(ant, name, clazz = nil)
+ @ant, @name, @clazz = ant, name, clazz
end
- end
- # This also subsumes configureId to only have to traverse args once
- def assign_attributes(instance, args)
- @ant.project.log "instance.task_name #{instance.task_name} #{name}", 5
- wrapper = RuntimeConfigurable.new instance, instance.task_name
- args.each do |key, value|
- # FIXME: Infinite recursion and only single expression expansion
- while value =~ /\$\{([^\}]+)\}/
- value.gsub!(/\$\{[^\}]+\}/, @ant.project.get_property($1).to_s)
+ def call(parent, args={}, &code)
+ element = create parent
+ assign_attributes element, args
+ define_nested_elements element if @clazz
+ code.arity==1 ? code[element] : element.instance_eval(&code) if
block_given?
+ if parent.respond_to? :add_task # Target
+ @ant.project.log "Adding #{name} to #{parent}", 5
+ parent.add_task element
+ elsif parent.respond_to? :add_child # Task
+ @ant.project.log "Adding #{name} to #{parent.component_name}", 5
+ parent.add_child element
+ parent.runtime_configurable_wrapper.add_child
element.runtime_configurable_wrapper
+ else # Just run it now
+ @ant.project.log "Executing #{name}", 5
+ element.owning_target = Target.new.tap {|t| t.name = ""}
+ element.maybe_configure
+ element.execute
+ end
+ end
+
+ private
+ def create(parent) # See ProjectHelper2.ElementHelper
+ UnknownElement.new(@name).tap do |e|
+ e.ant = @ant
+ e.project = @ant.project
+ e.task_name = @name
+ e.location = Ant.location_from_caller
+ e.owning_target = @ant.current_target
+ end
+ end
+
+ # This also subsumes configureId to only have to traverse args once
+ def assign_attributes(instance, args)
+ @ant.project.log "instance.task_name #{instance.task_name} #{name}", 5
+ wrapper = RuntimeConfigurable.new instance, instance.task_name
+ args.each do |key, value|
+ wrapper.set_attribute key, @ant.project.replace_properties(value)
end
- wrapper.set_attribute key, value
end
- end
- def define_nested_elements(instance)
- meta_class = class << instance; self; end
- @helper = IntrospectionHelper.get_helper(@ant.project, @clazz)
- @helper.get_nested_element_map.each do |element_name, clazz|
- element = @ant.acquire_element(element_name, clazz)
- meta_class.send(:define_method, Ant.safe_method_name(element_name)) do
|*args, &block|
- element.call(instance, *args, &block)
+ def define_nested_elements(instance)
+ meta_class = class << instance; self; end
+ @helper = IntrospectionHelper.get_helper(@ant.project, @clazz)
+ @helper.get_nested_element_map.each do |element_name, clazz|
+ element = @ant.acquire_element(element_name, clazz)
+ meta_class.send(:define_method, Ant.safe_method_name(element_name))
do |*args, &block|
+ element.call(instance, *args, &block)
+ end
end
end
end
diff --git a/lib/ruby/site_ruby/shared/ant/target.rb
b/lib/ruby/site_ruby/shared/ant/target.rb
index 27fbe82..456bfd3 100644
--- a/lib/ruby/site_ruby/shared/ant/target.rb
+++ b/lib/ruby/site_ruby/shared/ant/target.rb
@@ -1,9 +1,9 @@
require 'java'
require 'ant/ant'
-java_import org.apache.tools.ant.Target
-
class Ant
+ java_import org.apache.tools.ant.Target
+
class RakeTarget < Target
ALREADY_DEFINED_PREFIX = "rake_"
diff --git a/spec/java_integration/ant/ant_spec.rb
b/spec/java_integration/ant/ant_spec.rb
new file mode 100644
index 0000000..c68ed42
--- /dev/null
+++ b/spec/java_integration/ant/ant_spec.rb
@@ -0,0 +1,70 @@
+require File.expand_path('../../ant_spec_helper', __FILE__)
+
+describe Ant, "new", :type => :ant do
+ it "can be instantiated with a block" do
+ Ant.new do
+ self.class.should == Ant
+ end
+ end
+
+ it "can be instantiated with a block whose single argument receives the
Ant instance" do
+ Ant.new do |ant|
+ self.class.should_not == Ant
+ ant.class.should == Ant
+ end
+ end
+
+ it "should execute top-level tasks as it encounters them" do
+ Ant.new do |ant|
+ ant.properties["foo"].should_not == "bar"
+ ant.property :name => "foo", :value => "bar"
+ ant.properties["foo"].should == "bar"
+ end
+ end
+end
+
+describe Ant, :type => :ant do
+ before :each do
+ @ant = Ant.new :basedir => "/tmp", :run => false, :output_level => 0
+ end
+
+ it "should define methods corresponding to ant tasks" do
+ @ant.methods.should include("java", "antcall", "property", "import",
"path", "patternset")
+ end
+
+ it "should have a valid location" do
+ File.should be_exist(@ant.location.file_name)
+ end
+
+ it "should execute the default target" do
+ @ant.target("default") { property :name => "spec", :value => "example" }
+ @ant.project.default = "default"
+ @ant.execute_default
+ @ant.properties["spec"].should == "example"
+ end
+
+ it "should execute the specified target" do
+ @ant.target("a") { property :name => "a", :value => "true" }
+ @ant.target("b") { property :name => "b", :value => "true" }
+ @ant.execute_target("a")
+ @ant.properties["a"].should == "true"
+ @ant["b"].execute
+ @ant.properties["b"].should == "true"
+ end
+
+ it "should raise when a bogus target is executed" do
+ lambda { @ant["bogus"].execute }.should raise_error
+ end
+
+ it "should handle -Dkey=value arguments from the command-line" do
+ @ant.project.default = "help"
+ @ant.process_arguments(["-Dcommand.line.msg=hello", "help"], false)
+ @ant.define_tasks do
+ target :help do
+ property :name => "msg", :value => "${command.line.msg}"
+ end
+ end
+ @ant.run
+ @ant.properties["msg"].should == "hello"
+ end
+end
diff --git a/spec/java_integration/ant/project_spec.rb
b/spec/java_integration/ant/project_spec.rb
new file mode 100644
index 0000000..d907d86
--- /dev/null
+++ b/spec/java_integration/ant/project_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../ant_spec_helper', __FILE__)
+
+describe Ant, "project", :type => :ant do
+ before :each do
+ @ant = Ant.new :name => "spec project", :description => "spec
description", :basedir => "/tmp", :run => false
+ end
+
+ it "should have the 'basedir' set" do
+ @ant.project.base_dir.path.should == "/tmp"
+ end
+
+ it "should have a project helper created" do
+
@ant.project.get_reference(Ant::ProjectHelper::PROJECTHELPER_REFERENCE).should
be_kind_of(Ant::ProjectHelper)
+ end
+
+ it "should have a logger set" do
+ @ant.project.build_listeners.should_not be_empty
+ end
+
+ it "should have a name and description" do
+ @ant.project.name.should == "spec project"
+ @ant.project.description.should == "spec description"
+ end
+end
diff --git a/spec/java_integration/ant/target_spec.rb
b/spec/java_integration/ant/target_spec.rb
new file mode 100644
index 0000000..c2aa3d6
--- /dev/null
+++ b/spec/java_integration/ant/target_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../ant_spec_helper', __FILE__)
+
+describe Ant, "targets", :type => :ant do
+ it "should delay executing tasks in targets until the target is executed"
do
+ ant = Ant.new :name => "foo", :output_level => 0 do
+ target :foo do
+ property :name => "foo", :value => "bar"
+ end
+ end
+ ant.properties["foo"].should_not == "bar"
+ ant.execute_target(:foo)
+ ant.properties["foo"].should == "bar"
+ end
+
+ it "#ant should accumulate targets and tasks in the same global project" do
+ ant do
+ target :a
+ end
+ ant do
+ target :b
+ end
+ ant.project.targets.keys.to_a.should include("a", "b")
+ end
+end
diff --git a/spec/java_integration/ant/task_spec.rb
b/spec/java_integration/ant/task_spec.rb
new file mode 100644
index 0000000..e09d65e
--- /dev/null
+++ b/spec/java_integration/ant/task_spec.rb
@@ -0,0 +1,80 @@
+require File.expand_path('../../ant_spec_helper', __FILE__)
+
+describe Ant, "tasks:", :type => :ant do
+ before :all do
+ # The single example ant project these specs will validate
+ @output = output = "ant-file#{rand}.txt"
+ @ant = Ant.new :output_level => 0 do
+ property :name => "jar", :value => "spec-test.jar"
+ property :name => "dir", :value => "build"
+ taskdef :name => "jarjar", :classname =>
"com.tonicsystems.jarjar.JarJarTask",
+ :classpath => "${basedir}/build_lib/jarjar-1.0.jar"
+
+ target :jar do
+ jar :destfile => "${jar}", :compress => "true", :index => "true" do
+ fileset :dir => "${dir}"
+ end
+ end
+
+ target :jarjar do
+ jarjar :destfile => "${jar}", :compress => "true" do
+ fileset :dir => "${dir}"
+ zipfileset :src => "./lib/jruby.jar"
+ end
+ end
+
+ macrodef :name => "greet" do
+ attribute :name => "msg"
+ sequential do
+ echo :message => "Hello @{msg}", :file => "#{output}"
+ end
+ end
+
+ target :greet do
+ greet :msg => "Ant"
+ end
+ end
+ end
+
+ after :all do
+ File.unlink(@output) if File.exist?(@output)
+ end
+
+ describe "jar" do
+ subject do
+ @ant.project.targets["jar"]
+ end
+
+ it { should have_valid_tasks }
+
+ it { should have_structure([{:_name => "jar", :destfile =>
"spec-test.jar", :compress => "true", :index => "true",
+ :_children => [ { :_name => "fileset", :dir
=> "build" }] }]) }
+
+ it { should have_configured_structure([{:_type =>
"org.apache.tools.ant.taskdefs.Jar",
+ :_children => [{:_type =>
"org.apache.tools.ant.types.FileSet"}] }]) }
+
+ end
+
+ describe "jarjar" do
+ subject do
+ @ant.project.targets["jarjar"]
+ end
+
+ it { should have_valid_tasks }
+
+ it { should have_structure([{:_name => "jarjar", :destfile =>
"spec-test.jar", :compress => "true",
+ :_children => [ { :_name => "fileset", :dir
=> "build" },
+ { :_name => "zipfileset",
:src => "./lib/jruby.jar" }] }]) }
+
+ it { should have_configured_structure([{:_type =>
"com.tonicsystems.jarjar.JarJarTask",
+ :_children => [{:_type =>
"org.apache.tools.ant.types.FileSet"},
+ {:_type =>
"org.apache.tools.ant.types.ZipFileSet"}] }]) }
+ end
+
+ describe "macrodef" do
+ it "should be defined and invokable from a target" do
+ @ant.execute_target(:greet)
+ File.read(@output).should == "Hello Ant"
+ end
+ end
+end
diff --git a/spec/java_integration/ant_spec_helper.rb
b/spec/java_integration/ant_spec_helper.rb
new file mode 100644
index 0000000..eace9fa
--- /dev/null
+++ b/spec/java_integration/ant_spec_helper.rb
@@ -0,0 +1,141 @@
+require File.expand_path('../spec_helper', __FILE__)
+require 'ant'
+
+class Ant
+ module Spec
+ class AntExampleGroup < ::Spec::Example::ExampleGroup
+ after :each do
+ Ant.send(:instance_variable_set, "@ant", nil)
+ end
+
+ # Validates the tasks in a target look sane. Currently just
+ # checks owning_target.
+ class ValidTasksMatcher
+ def description
+ "have valid tasks"
+ end
+
+ def matches?(target)
+ @target = target
+ result = true
+ @target.tasks.each do |t|
+ result &&= (t.owning_target == @target)
+ end
+ result
+ end
+
+ def failure_message_for_should
+ "expected #{@target.inspect} to have valid tasks"
+ end
+
+ def failure_message_for_should_not
+ "expected #{@target.inspect} to not have valid tasks"
+ end
+ end
+
+ # Allows matching task structure with a nested hash as follows.
+ #
+ # { :_name => "jar", :destfile => "spec-test.jar", :compress =>
"true", :index => "true",
+ # :_children => [
+ # { :_name => "fileset", :dir => "build" }
+ # ]}
+ #
+ # would match the following:
+ #
+ # jar :destfile => "spec-test.jar", :compress => "true", :index =>
"true" do
+ # fileset :dir => "build"
+ # end
+ #
+ class TaskStructureMatcher
+ def initialize(hash, configure = false)
+ @expected = hash
+ @configure = configure
+ end
+
+ def description
+ "have the specified #{(@configure ? 'configured' : 'element')}
structure"
+ end
+
+ def matches?(actual)
+ @actual = actual
+ result = true
+ tasks = actual.tasks
+ if Hash === @expected && tasks.length != 1 || tasks.length !=
@expected.length
+ @message = "task list length different"
+ return false
+ end
+ @expected.each_with_index do |h,i|
+ tasks[i].maybe_configure if @configure
+ result &&= match_wrapper(h, tasks[i].wrapper)
+ end
+ result
+ end
+
+ def match_wrapper(hash, wrapper, name = nil)
+ hname = hash[:_name] ? hash[:_name] : '<?>'
+ if name
+ name = "#{name} => #{hname}"
+ else
+ name = hname
+ end
+
+ # name
+ if hash[:_name] && hash[:_name] != wrapper.element_tag
+ @message = "name different: expected #{hash[:_name].inspect} but
was #{wrapper.element_tag.inspect}"
+ return false
+ end
+
+ # proxy class name
+ if hash[:_type] && (wrapper.proxy.nil? || hash[:_type] !=
wrapper.proxy.java_class.name)
+ @message = "type different: expected #{hash[:_type]} but was
#{wrapper.proxy.java_class.name}"
+ return false
+ end
+
+ # attributes
+ hash.keys.select {|k| k.to_s !~ /^_/}.each do |k|
+ unless wrapper.attribute_map.containsKey(k.to_s)
+ @message = "'#{name} => #{k}' attribute missing"
+ return false
+ end
+
+ if hash[k] != wrapper.attribute_map[k.to_s]
+ @message = "'#{name} => #{k}' attribute different: expected
#{hash[k].inspect} but was #{wrapper.attribute_map[k.to_s].inspect}"
+ return false
+ end
+ end
+
+ # children, recursively
+ children = wrapper.children.to_a
+ (hash[:_children] || []).each_with_index do |h,i|
+ return false unless match_wrapper(h, children[i], name)
+ end
+ true
+ end
+
+ def failure_message_for_should
+ require 'pp'
+ "expected #{@actual.name} to have
structure:\n#{@expected.pretty_inspect}\n#{@message}"
+ end
+
+ def failure_message_for_should_not
+ require 'pp'
+ "expected #{@actual.name} to not have
structure:\n#{@expected.pretty_inspect}\n#{@message}"
+ end
+ end
+
+ def have_valid_tasks
+ ValidTasksMatcher.new
+ end
+
+ def have_structure(hash)
+ TaskStructureMatcher.new(hash)
+ end
+
+ def have_configured_structure(hash)
+ TaskStructureMatcher.new(hash, true)
+ end
+
+ ::Spec::Example::ExampleGroupFactory.register(:ant, self)
+ end
+ end
+end
|
[jruby~main:f25167ae] Ant integration: Get _element working better |
nicksieger | 03/04/2010 |





