spec/aquarium/aspects/aspect_invocation_spec.rb in aquarium-0.1.7 vs spec/aquarium/aspects/aspect_invocation_spec.rb in aquarium-0.1.8
- old
+ new
@@ -1,14 +1,39 @@
require File.dirname(__FILE__) + '/../spec_helper.rb'
require File.dirname(__FILE__) + '/../spec_example_classes'
require 'aquarium/aspects/aspect'
require 'aquarium/aspects/dsl'
+require 'aquarium/utils/array_utils'
+require 'profiler'
+
include Aquarium::Aspects
+include Aquarium::Utils::ArrayUtils
-describe Aspect, "#new with invalid invocation parameter list" do
- it "should have as the first parameter at least one of :around, :before, :after, :after_returning, and :after_raising." do
+
+def aspects_should_be_equal num_jps, aspect1, aspect2
+ # We don't use @aspect1.should eql(@aspect2) because the "specifications" are different.
+ aspect1.pointcuts.size.should == 1
+ aspect2.pointcuts.size.should == 1
+ aspect1.pointcuts.should eql(aspect2.pointcuts)
+ aspect1.advice.should eql(@advice)
+ aspect2.advice.should eql(@advice)
+ join_points_should_be_equal num_jps, aspect1, aspect2
+end
+
+def join_points_should_be_equal num_jps, aspect1, aspect2
+ aspect1.join_points_matched.size.should == num_jps
+ aspect2.join_points_matched.size.should == num_jps
+ aspect1.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
+ aspect2.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
+ aspect1.join_points_matched.should eql(aspect2.join_points_matched)
+ aspect1.join_points_not_matched.should eql(aspect2.join_points_not_matched)
+end
+
+
+describe Aspect, "#new parameters that specify the kind of advice" do
+ it "should require the kind of advice as the first parameter." do
lambda { Aspect.new :pointcut => {:type => Watchful} }.should raise_error(Aquarium::Utils::InvalidOptions)
end
it "should contain no other advice types if :around advice specified." do
lambda { Aspect.new :around, :before, :pointcut => {:type => Watchful} }.should raise_error(Aquarium::Utils::InvalidOptions)
@@ -20,13 +45,11 @@
it "should allow only one of :after, :after_returning, or :after_raising advice to be specified." do
lambda { Aspect.new :after, :after_returning, :pointcut => {:type => Watchful} }.should raise_error(Aquarium::Utils::InvalidOptions)
lambda { Aspect.new :after, :after_raising, :pointcut => {:type => Watchful} }.should raise_error(Aquarium::Utils::InvalidOptions)
lambda { Aspect.new :after_returning, :after_raising, :pointcut => {:type => Watchful} }.should raise_error(Aquarium::Utils::InvalidOptions)
end
-end
-describe Aspect, "#new, when the arguments contain more than one advice type," do
it "should allow :before to be specified with :after." do
lambda { Aspect.new :before, :after, :pointcut => {:type => Watchful}, :noop => true }.should_not raise_error(Aquarium::Utils::InvalidOptions)
end
it "should allow :before to be specified with :after_returning." do
@@ -36,31 +59,758 @@
it "should allow :before to be specified with :after_raising." do
lambda { Aspect.new :before, :after_raising, :pointcut => {:type => Watchful}, :noop => true }.should_not raise_error(Aquarium::Utils::InvalidOptions)
end
end
-def aspects_should_be_equal num_jps, aspect1, aspect2
- # We don't use @aspect1.should eql(@aspect2) because the "specifications" are different.
- aspect1.pointcuts.size.should == 1
- aspect2.pointcuts.size.should == 1
- aspect1.pointcuts.should eql(aspect2.pointcuts)
- aspect1.advice.should eql(@advice)
- aspect2.advice.should eql(@advice)
- join_points_should_be_equal num_jps, aspect1, aspect2
+describe Aspect, "#new parameters that specify join points" do
+ it "should contain at least one of :method(s), :pointcut(s), :type(s), or :object(s)." do
+ lambda {Aspect.new(:after) {|jp, *args| true}}.should raise_error(Aquarium::Utils::InvalidOptions)
+ end
+
+ it "should contain at least one of :pointcut(s), :type(s), or :object(s) unless :default_object => object is given." do
+ aspect = Aspect.new(:after, :default_object => Watchful.new, :methods => :public_watchful_method) {|jp, *args| true}
+ aspect.unadvise
+ end
+
+ it "should not contain :pointcut(s) and either :type(s) or :object(s)." do
+ lambda {Aspect.new(:after, :pointcuts => {:type => Watchful, :methods => :public_watchful_method}, :type => Watchful, :methods => :public_watchful_method) {|jp, *args| true}}.should raise_error(Aquarium::Utils::InvalidOptions)
+ lambda {Aspect.new(:after, :pointcuts => {:type => Watchful, :methods => :public_watchful_method}, :object => Watchful.new, :methods => :public_watchful_method) {|jp, *args| true}}.should raise_error(Aquarium::Utils::InvalidOptions)
+ end
+
+ it "should include an advice block or :advice => advice parameter." do
+ lambda {Aspect.new(:after, :type => Watchful, :methods => :public_watchful_method)}.should raise_error(Aquarium::Utils::InvalidOptions)
+ end
end
-def join_points_should_be_equal num_jps, aspect1, aspect2
- aspect1.join_points_matched.size.should == num_jps
- aspect2.join_points_matched.size.should == num_jps
- aspect1.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
- aspect2.join_points_matched.each {|jp| @expected_methods.should include(jp.method_name)}
- aspect1.join_points_matched.should eql(aspect2.join_points_matched)
- aspect1.join_points_not_matched.should eql(aspect2.join_points_not_matched)
+
+describe Aspect, "#new :type parameter" do
+ it "should be accepted as a synonym for :types" do
+ @advice = Proc.new {}
+ @expected_methods = [:public_watchful_method]
+ aspect1 = Aspect.new :before, :type => Watchful, :method => @expected_methods, :advice => @advice
+ aspect2 = Aspect.new :before, :types => Watchful, :method => @expected_methods, :advice => @advice
+ aspects_should_be_equal 1, aspect1, aspect2
+ aspect1.unadvise
+ aspect2.unadvise
+ end
end
-describe Aspect, "#new arguments for specifying the types and methods" do
+describe Aspect, "#new :pointcut parameter" do
+ it "should be accepted as a synonym for :pointcuts" do
+ @advice = Proc.new {}
+ @expected_methods = [:public_watchful_method]
+ aspect1 = Aspect.new :before, :pointcut => {:type => Watchful, :method => @expected_methods}, :advice => @advice
+ aspect2 = Aspect.new :before, :pointcuts => {:type => Watchful, :method => @expected_methods}, :advice => @advice
+ aspects_should_be_equal 1, aspect1, aspect2
+ aspect1.unadvise
+ aspect2.unadvise
+ end
+end
+
+describe Aspect, "#new :object parameter" do
+ it "should be accepted as a synonym for :objects" do
+ @advice = Proc.new {}
+ @expected_methods = [:public_watchful_method]
+ watchful = Watchful.new
+ aspect1 = Aspect.new :before, :object => watchful, :method => @expected_methods, :advice => @advice
+ aspect2 = Aspect.new :before, :objects => watchful, :method => @expected_methods, :advice => @advice
+ aspects_should_be_equal 1, aspect1, aspect2
+ aspect1.unadvise
+ aspect2.unadvise
+ end
+end
+
+describe Aspect, "#new :method parameter" do
+ it "should be accepted as a synonym for :methods" do
+ @advice = Proc.new {}
+ @expected_methods = [:public_watchful_method]
+ aspect1 = Aspect.new :before, :type => Watchful, :method => @expected_methods, :advice => @advice
+ aspect2 = Aspect.new :before, :type => Watchful, :methods => @expected_methods, :advice => @advice
+ aspects_should_be_equal 1, aspect1, aspect2
+ aspect1.unadvise
+ aspect2.unadvise
+ end
+end
+
+describe Aspect, "#new :attribute parameter" do
+ it "should be accepted as a synonym for :attributes" do
+ @advice = Proc.new {}
+ @expected_methods = [:public_watchful_method_args, :public_watchful_method_args=]
+ aspect1 = Aspect.new :before, :type => Watchful, :attribute => @expected_methods, :advice => @advice
+ aspect2 = Aspect.new :before, :type => Watchful, :attributes => @expected_methods, :advice => @advice
+ aspects_should_be_equal 2, aspect1, aspect2
+ aspect1.unadvise
+ aspect2.unadvise
+ end
+end
+
+
+describe Aspect, "#new with a :type(s) parameter and a :method(s) parameter" do
before :each do
+ @protection = 'public'
+ @are_class_methods = false
+ @method_options = []
+ end
+
+ def do_type_spec
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :types => @type_spec, :methods => @method_spec, :method_options => @method_options do |jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ end
+ if @are_class_methods
+ Watchful.method("#{@protection}_class_watchful_method").call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ else
+ Watchful.new.method("#{@protection}_watchful_method").call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ end
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept :type(s) => [T1, ...], :methods => [m, ...]" do
+ @type_spec = [Watchful]
+ @method_spec = [:public_watchful_method]
+ do_type_spec
+ end
+
+ it "should accept :type(s) => [T1, ...], :methods => m" do
+ @type_spec = [Watchful]
+ @method_spec = :public_watchful_method
+ do_type_spec
+ end
+
+ it "should accept :type(s) => [T1, ...], :methods => /m/" do
+ @type_spec = [Watchful]
+ @method_spec = /watchful_method/
+ do_type_spec
+ end
+
+ it "should accept :type(s) => T1, :methods => [m, ...]" do
+ @type_spec = Watchful
+ @method_spec = [:public_watchful_method]
+ do_type_spec
+ end
+
+ it "should accept :type(s) => T1, :methods => m" do
+ @type_spec = Watchful
+ @method_spec = :public_watchful_method
+ do_type_spec
+ end
+
+ it "should accept :type(s) => T1, :methods => /m/" do
+ @type_spec = Watchful
+ @method_spec = /watchful_method/
+ do_type_spec
+ end
+
+ it "should accept :type(s) => /T1/, :methods => [m, ...]" do
+ @type_spec = /Watchful/
+ @method_spec = [:public_watchful_method]
+ do_type_spec
+ end
+
+ it "should accept :type(s) => /T1/, :methods => m" do
+ @type_spec = /Watchful/
+ @method_spec = :public_watchful_method
+ do_type_spec
+ end
+
+ it "should accept :type(s) => /T1/, :methods => /m/" do
+ @type_spec = /Watchful/
+ @method_spec = /watchful_method/
+ do_type_spec
+ end
+
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [:exclude_ancestor_methods] to exclude methods defined in ancestors" do
+ @type_spec = /Watchful/
+ @method_spec = /watchful_method/
+ @method_options = [:exclude_ancestor_methods]
+ do_type_spec
+ end
+
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [:instance, :public] to match only instance and public (both are the defaults) methods" do
+ @type_spec = /Watchful/
+ @method_spec = /watchful_method/
+ @method_options = [:instance, :public]
+ do_type_spec
+ end
+
+ %w[public protected private].each do |protection|
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [#{protection.intern}] to match only instance (default) #{protection} methods" do
+ @type_spec = /Watchful/
+ @method_spec = /watchful_method/
+ @method_options = [protection.intern]
+ @protection = protection
+ do_type_spec
+ end
+ end
+
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [:class] to match only public (default) class methods" do
+ @type_spec = /Watchful/
+ @method_spec = /watchful_method/
+ @method_options = [:class]
+ @are_class_methods = true
+ do_type_spec
+ end
+
+ %w[public private].each do |protection|
+ it "should accept :type(s) => ..., :methods => ..., :method_options => [:class, :#{protection.intern}] to match only class #{protection} methods" do
+ @type_spec = /Watchful/
+ @method_spec = /watchful_method/
+ @method_options = [:class, protection.intern]
+ @protection = protection
+ @are_class_methods = true
+ do_type_spec
+ end
+ end
+end
+
+
+describe Aspect, "#new with a :type(s) parameter and a :attribute(s) parameter" do
+ before :each do
+ @protection = 'public'
+ @attribute_options = []
+ @are_class_methods = false
+ end
+
+ def do_type_attribute_spec
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :types => @type_spec, :attributes => @attribute_spec, :attribute_options => @attribute_options do |jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ expected_args = make_array(@expected_args)
+ args.should == expected_args
+ args.size.should == expected_args.size
+ end
+ watchful = Watchful.new
+ @expected_args = nil
+ watchful.method("#{@protection}_watchful_method_args".intern).call
+ @expected_args = :a1
+ watchful.method("#{@protection}_watchful_method_args=".intern).call @expected_args
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept :type(s) => [T1, ...], :attribute(s) => [a, ...]" do
+ @type_spec = [Watchful]
+ @attribute_spec = [:public_watchful_method_args]
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => [T1, ...], :attribute(s) => a" do
+ @type_spec = [Watchful]
+ @attribute_spec = :public_watchful_method_args
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => [T1, ...], :attribute(s) => /a/" do
+ @type_spec = [Watchful]
+ @attribute_spec = /watchful_method_args/
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => T1, :attribute(s) => [a]" do
+ @type_spec = Watchful
+ @attribute_spec = [:public_watchful_method_args]
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => T1, :attribute(s) => a" do
+ @type_spec = Watchful
+ @attribute_spec = :public_watchful_method_args
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => T1, :attribute(s) => /a/" do
+ @type_spec = Watchful
+ @attribute_spec = /watchful_method_args/
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => /T1/, :attribute(s) => [a, ...]" do
+ @type_spec = /Watchful/
+ @attribute_spec = [:public_watchful_method_args]
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => /T1/, :attribute(s) => a" do
+ @type_spec = /Watchful/
+ @attribute_spec = :public_watchful_method_args
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => /T1/, :attribute(s) => a" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:readers, :writers] to include both attribute reader and writer methods (default)" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:readers, :writers]
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:readers] to include only attribute reader methods" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:readers]
+ do_type_attribute_spec
+ end
+
+ it "should accept attribute option :reader as a synonym for :readers" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:reader]
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:writers] to include only attribute writer methods" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:writers]
+ do_type_attribute_spec
+ end
+
+ it "should accept attribute option :writer as a synonym for :writers" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:writer]
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:class, :readers, :writers] to include both attribute reader and writer methods (default) for class methods" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:class, :readers, :writers]
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:class, :readers] to include only attribute reader class methods" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:class, :readers]
+ do_type_attribute_spec
+ end
+
+ it "should accept :type(s) => ..., :attributes => ..., :attribute_options => [:class, :writers] to include only attribute writer class methods" do
+ @type_spec = /Watchful/
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:class, :writers]
+ do_type_attribute_spec
+ end
+end
+
+describe Aspect, "#new with a :object(s) parameter and a :method(s) parameter" do
+ before :each do
+ @watchful1 = Watchful.new
+ @watchful2 = Watchful.new
+ @protection = 'public'
+ @method_options = []
+ end
+
+ def do_object_spec
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :objects => @object_spec, :methods => @method_spec, :method_options => @method_options do |jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ end
+ make_array(@object_spec).each do |object|
+ object.method("#{@protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ end
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept :object(s) => [o1, ...], :methods => [m, ...]" do
+ @object_spec = [@watchful1, @watchful2]
+ @method_spec = [:public_watchful_method]
+ do_object_spec
+ end
+
+ it "should accept :object(s) => [o1, ...], :methods => m" do
+ @object_spec = [@watchful1, @watchful2]
+ @method_spec = :public_watchful_method
+ do_object_spec
+ end
+
+ it "should accept :object(s) => [o1, ...], :methods => /m/" do
+ @object_spec = [@watchful1, @watchful2]
+ @method_spec = /watchful_method/
+ do_object_spec
+ end
+
+ it "should accept :object(s) => o1, :methods => [m, ...]" do
+ @object_spec = @watchful1
+ @method_spec = [:public_watchful_method]
+ do_object_spec
+ end
+
+ it "should accept :object(s) => o1, :methods => m" do
+ @object_spec = @watchful1
+ @method_spec = :public_watchful_method
+ do_object_spec
+ end
+
+ it "should accept :object(s) => o1, :methods => /m/" do
+ @object_spec = @watchful1
+ @method_spec = /watchful_method/
+ do_object_spec
+ end
+
+ it "should accept :object(s) => ..., :methods => ..., :method_options => [:exclude_ancestor_methods] to exclude methods defined in ancestors" do
+ @object_spec = @watchful1
+ @method_spec = /watchful_method/
+ @method_options = [:exclude_ancestor_methods]
+ do_object_spec
+ end
+
+ it "should accept :object(s) => ..., :methods => ..., :method_options => [:instance, :public] to match only instance and public (both are the defaults) methods" do
+ @object_spec = @watchful1
+ @method_spec = /watchful_method/
+ @method_options = [:instance, :public]
+ do_object_spec
+ end
+
+ %w[public protected private].each do |protection|
+ it "should accept :object(s) => ..., :methods => ..., :method_options => [#{protection.intern}] to match only instance (default) #{protection} methods" do
+ @object_spec = @watchful1
+ @method_spec = /watchful_method/
+ @method_options = [protection.intern]
+ @protection = protection
+ do_object_spec
+ end
+
+ it "should accept :object(s) => ..., :methods => ..., :method_options => [:instance, #{protection.intern}] to match only instance #{protection} methods" do
+ @object_spec = @watchful1
+ @method_spec = /watchful_method/
+ @method_options = [:instance, protection.intern]
+ @protection = protection
+ do_object_spec
+ end
+ end
+end
+
+describe Aspect, "#new with a :object(s) parameter and a :attribute(s) parameter" do
+ before :each do
+ @watchful1 = Watchful.new
+ @watchful2 = Watchful.new
+ @protection = 'public'
+ @attribute_options = []
+ end
+
+ def do_object_attribute_spec
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :objects => @object_spec, :attributes => @attribute_spec, :attribute_options => @attribute_options do |jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ expected_args = make_array(@expected_args)
+ args.should == expected_args
+ args.size.should == expected_args.size
+ end
+ make_array(@object_spec).each do |object|
+ @expected_args = nil
+ object.method("#{@protection}_watchful_method_args".intern).call
+ @expected_args = :a1
+ object.method("#{@protection}_watchful_method_args=".intern).call @expected_args
+ advice_called.should be_true
+ end
+ aspect.unadvise
+ end
+
+ it "should accept :object(s) => [T1, ...], :attribute(s) => [a, ...]" do
+ @object_spec = [@watchful1, @watchful2]
+ @attribute_spec = [:public_watchful_method_args]
+ do_object_attribute_spec
+ end
+
+ it "should accept :object(s) => [T1, ...], :attribute(s) => a" do
+ @object_spec = [@watchful1, @watchful2]
+ @attribute_spec = :public_watchful_method_args
+ do_object_attribute_spec
+ end
+
+ it "should accept :object(s) => [T1, ...], :attribute(s) => /a/" do
+ @object_spec = [@watchful1, @watchful2]
+ @attribute_spec = /watchful_method_args/
+ do_object_attribute_spec
+ end
+
+ it "should accept :object(s) => T1, :attribute(s) => [a]" do
+ @object_spec = @watchful1
+ @attribute_spec = [:public_watchful_method_args]
+ do_object_attribute_spec
+ end
+
+ it "should accept :object(s) => T1, :attribute(s) => a" do
+ @object_spec = @watchful1
+ @attribute_spec = :public_watchful_method_args
+ do_object_attribute_spec
+ end
+
+ it "should accept :object(s) => T1, :attribute(s) => /a/" do
+ @object_spec = @watchful1
+ @attribute_spec = /watchful_method_args/
+ do_object_attribute_spec
+ end
+
+ it "should accept :object(s) => ..., :attributes => ..., :attribute_options => [:readers, :writers] to include both attribute reader and writer methods (default)" do
+ @object_spec = @watchful1
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:readers, :writers]
+ do_object_attribute_spec
+ end
+
+ it "should accept :object(s) => ..., :attributes => ..., :attribute_options => [:readers] to include only attribute reader methods" do
+ @object_spec = @watchful1
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:readers]
+ do_object_attribute_spec
+ end
+
+ it "should accept attribute option :reader as a synonym for :readers" do
+ @object_spec = @watchful1
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:reader]
+ do_object_attribute_spec
+ end
+
+ it "should accept :object(s) => ..., :attributes => ..., :attribute_options => [:writers] to include only attribute writer methods" do
+ @object_spec = @watchful1
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:writers]
+ do_object_attribute_spec
+ end
+
+ it "should accept attribute option :writer as a synonym for :writers" do
+ @object_spec = @watchful1
+ @attribute_spec = /watchful_method_args/
+ @attribute_options = [:writer]
+ do_object_attribute_spec
+ end
+end
+
+describe Aspect, "#new with a :pointcut parameter taking a hash with type specifications" do
+ before :each do
+ @protection = 'public'
+ @are_class_methods = false
+ end
+
+ def do_type_pointcut_spec
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :pointcut => @pointcut_hash do |jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ end
+ if @are_class_methods
+ Watchful.method("#{@protection}_class_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ else
+ Watchful.new.method("#{@protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ end
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept {:type(s) => [T1, ...], :methods => [m, ...]} " do
+ @pointcut_hash = {:type => [Watchful], :methods => [:public_watchful_method]}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => [T1, ...], :methods => m} " do
+ @pointcut_hash = {:type => [Watchful], :methods => :public_watchful_method}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => [T1, ...], :methods => /m/} " do
+ @pointcut_hash = {:type => [Watchful], :methods => /watchful_method/}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => T1, :methods => [m, ...]} " do
+ @pointcut_hash = {:type => Watchful, :methods => [:public_watchful_method]}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => T1, :methods => m} " do
+ @pointcut_hash = {:type => Watchful, :methods => :public_watchful_method}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => T1, :methods => /m/} " do
+ @pointcut_hash = {:type => Watchful, :methods => /watchful_method/}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => /T1/, :methods => [m, ...]} " do
+ @pointcut_hash = {:type => /Watchful/, :methods => [:public_watchful_method]}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => /T1/, :methods => m} " do
+ @pointcut_hash = {:type => /Watchful/, :methods => :public_watchful_method}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => /T1/, :methods => /m/} " do
+ @pointcut_hash = {:type => /Watchful/, :methods => /watchful_method/}
+ do_type_pointcut_spec
+ end
+
+ %w[public protected private].each do |protection|
+ it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:instance, #{protection}]} " do
+ @protection = protection
+ @pointcut_hash = {:type => Watchful, :methods => /watchful_method/, :method_options =>[:instance, protection.intern]}
+ do_type_pointcut_spec
+ end
+ end
+
+ %w[public private].each do |protection|
+ it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:class, #{protection}]} " do
+ @pointcut_hash = {:type => Watchful, :methods => /class_watchful_method/, :method_options =>[:class, protection.intern]}
+ @protection = protection
+ @are_class_methods = true
+ do_type_pointcut_spec
+ end
+ end
+
+ it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:instance]} defaults to public methods" do
+ @pointcut_hash = {:type => Watchful, :methods => /watchful_method/, :method_options =>[:instance]}
+ do_type_pointcut_spec
+ end
+
+ it "should accept {:type(s) => T1, :methods => /m/, :method_options =>[:class]} defaults to public class methods" do
+ @pointcut_hash = {:type => Watchful, :methods => /watchful_method/, :method_options =>[:class]}
+ @are_class_methods = true
+ do_type_pointcut_spec
+ end
+end
+
+describe Aspect, "#new with a :pointcut parameter taking a hash with object specifications" do
+ before :each do
+ @protection = 'public'
+ @expected_advice_count = 2
+ @watchful1 = Watchful.new
+ @watchful2 = Watchful.new
+ end
+
+ def do_object_pointcut_spec
+ aspect = nil
+ advice_count = 0
+ aspect = Aspect.new :before, :pointcut => @pointcut_hash do |jp, *args|
+ advice_count += 1
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ end
+ @watchful1.method("#{@protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ @watchful2.method("#{@protection}_watchful_method".intern).call :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_count.should == @expected_advice_count
+ aspect.unadvise
+ end
+
+ it "should accept {:objects => [o1, ...], :methods => [m, ...]} " do
+ @pointcut_hash = {:objects => [@watchful1, @watchful2], :methods => [:public_watchful_method]}
+ do_object_pointcut_spec
+ end
+
+ it "should accept {:objects => [o1, ...], :methods => m} " do
+ @pointcut_hash = {:objects => [@watchful1, @watchful2], :methods => :public_watchful_method}
+ do_object_pointcut_spec
+ end
+
+ it "should accept {:objects => [o1, ...], :methods => /m/} " do
+ @pointcut_hash = {:objects => [@watchful1, @watchful2], :methods => /watchful_method/}
+ do_object_pointcut_spec
+ end
+
+ it "should accept {:object => o1, :methods => [m, ...]} " do
+ @expected_advice_count = 1
+ @pointcut_hash = {:object => @watchful1, :methods => [:public_watchful_method]}
+ do_object_pointcut_spec
+ end
+
+ it "should accept {:objects => o1, :methods => m} " do
+ @expected_advice_count = 1
+ @pointcut_hash = {:objects => @watchful1, :methods => :public_watchful_method}
+ do_object_pointcut_spec
+ end
+
+ it "should accept {:objects => o1, :methods => /m/} " do
+ @expected_advice_count = 1
+ @pointcut_hash = {:objects => @watchful1, :methods => /watchful_method/}
+ do_object_pointcut_spec
+ end
+end
+
+describe Aspect, "#new with a :pointcut parameter and a Pointcut object or an array of Pointcuts" do
+ def do_pointcut_pointcut_spec
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :pointcut => @pointcuts do |jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ end
+ Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept a single Pointcut object." do
+ @pointcuts = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
+ do_pointcut_pointcut_spec
+ end
+
+ it "should accept an array of Pointcut objects." do
+ pointcut1 = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
+ pointcut2 = Pointcut.new :type => [Watchful], :methods => :public_class_watchful_method, :method_options => [:class]
+ @pointcuts = [pointcut1, pointcut2]
+ do_pointcut_pointcut_spec
+ end
+end
+
+describe Aspect, "#new with a :pointcut parameter and an array of Pointcuts" do
+ it "should treat the array as if it is one Pointcut \"or'ed\" together." do
+ advice_called = 0
+ advice = Proc.new {|jp, *args|
+ advice_called += 1
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ }
+ pointcut1 = Pointcut.new :type => [Watchful], :methods => :public_watchful_method
+ pointcut2 = Pointcut.new :type => [Watchful], :methods => :public_class_watchful_method, :method_options => [:class]
+ pointcut12 = pointcut1.or pointcut2
+ aspect1 = Aspect.new :before, :pointcut => [pointcut1, pointcut2], :advice => advice
+ Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ Watchful.public_class_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should == 2
+ aspect1.unadvise
+ advice_called = 0
+ aspect2 = Aspect.new :before, :pointcut => pointcut12, :advice => advice
+ Watchful.new.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ Watchful.public_class_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should == 2
+ aspect2.unadvise
+ aspect1.join_points_matched.should eql(aspect2.join_points_matched)
+ end
+end
+
+describe Aspect, "#new with a :type(s) parameter and a :method(s) parameter or one of several equivalent :pointcut parameters" do
+ before :each do
@advice = proc {|jp,*args| "advice"}
@expected_methods = [:public_watchful_method]
end
after :each do
@aspect1.unadvise
@@ -77,11 +827,11 @@
@aspect1 = Aspect.new :after, :type => Watchful, :method => :public_watchful_method, &@advice
pointcut = Aquarium::Aspects::Pointcut.new :type => Watchful, :method => :public_watchful_method
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
aspects_should_be_equal 1, @aspect1, @aspect2
end
-
+
it "should advise equivalent join points when :pointcut =>{:type => T, :method => m} is used or :pointcut => pointcut is used, where pointcut matches :type => T and :method => m." do
@aspect1 = Aspect.new :after, :pointcut => {:type => Watchful, :method => :public_watchful_method}, &@advice
pointcut = Aquarium::Aspects::Pointcut.new :type => Watchful, :method => :public_watchful_method
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
aspects_should_be_equal 1, @aspect1, @aspect2
@@ -93,15 +843,12 @@
@aspect2 = Aspect.new :after, :pointcut => join_point, &@advice
join_points_should_be_equal 1, @aspect1, @aspect2
end
end
-describe Aspect, "#new arguments for specifying the types and attributes" do
+describe Aspect, "#new with a :type(s) parameter and an :attributes(s) parameter or one of several equivalent :pointcut parameters" do
class ClassWithAttrib1
- def initialize *args
- @state = args
- end
def dummy; end
attr_accessor :state
end
before :each do
@@ -138,28 +885,26 @@
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
aspects_should_be_equal 2, @aspect1, @aspect2
end
it "should advise equivalent join points when :type => T and :attribute => a (the attribute's reader and writer) is used or :pointcut => [join_points] is used, where the join_points match :type => T and :method => :a and :method => :a=." do
- # pending "working on Pointcut.new first."
@aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, &@advice
join_point1 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state
join_point2 = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state=
@aspect2 = Aspect.new :after, :pointcut => Pointcut.new(:join_points => [join_point1, join_point2]), &@advice
join_points_should_be_equal 2, @aspect1, @aspect2
end
it "should advise an equivalent join point when :type => T and :method => :a= (the attribute's writer) is used or :pointcut => join_point is used, where join_point matches :type => T and :method => a=." do
- # pending "working on Pointcut.new first."
@aspect1 = Aspect.new :after, :type => ClassWithAttrib1, :attribute => :state, :attribute_options => [:writer], &@advice
join_point = Aquarium::Aspects::JoinPoint.new :type => ClassWithAttrib1, :method => :state=
@aspect2 = Aspect.new :after, :pointcut => join_point, &@advice
join_points_should_be_equal 1, @aspect1, @aspect2
end
end
-describe Aspect, "#new arguments for specifying the objects and methods" do
+describe Aspect, "#new with a :object(s) parameter and a :method(s) parameter or one of several equivalent :pointcut parameters" do
before :each do
@advice = proc {|jp,*args| "advice"}
@expected_methods = [:public_watchful_method]
end
after :each do
@@ -189,11 +934,11 @@
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
aspects_should_be_equal 1, @aspect1, @aspect2
end
end
-describe Aspect, "#new arguments for specifying the objects and attributes" do
+describe Aspect, "#new with a :object(s) parameter and an :attributes(s) parameter or one of several equivalent :pointcut parameters" do
class ClassWithAttrib2
def initialize *args
@state = args
end
def dummy; end
@@ -235,22 +980,580 @@
@aspect2 = Aspect.new :after, :pointcut => pointcut, &@advice
aspects_should_be_equal 2, @aspect1, @aspect2
end
it "should advise equivalent join points when :type => T and :attribute => a (the attribute's reader and writer) is used or :pointcut => [join_points] is used, where the join_points match :type => T and :method => :a and :method => :a=." do
- # pending "working on Pointcut.new first."
@aspect1 = Aspect.new :after, :object => @object, :attribute => :state, &@advice
join_point1 = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state
join_point2 = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state=
@aspect2 = Aspect.new :after, :pointcut => Pointcut.new(:join_points => [join_point1, join_point2]), &@advice
join_points_should_be_equal 2, @aspect1, @aspect2
end
it "should advise an equivalent join point when :type => T and :method => :a= (the attribute's writer) is used or :pointcut => join_point is used, where join_point matches :type => T and :method => a=." do
- # pending "working on Pointcut.new first."
@aspect1 = Aspect.new :after, :object => @object, :attribute => :state, :attribute_options => [:writer], &@advice
join_point = Aquarium::Aspects::JoinPoint.new :object => @object, :method => :state=
@aspect2 = Aspect.new :after, :pointcut => join_point, &@advice
join_points_should_be_equal 1, @aspect1, @aspect2
end
end
+describe Aspect, "#new block for advice" do
+ it "should accept a block as the advice to use." do
+ watchful = Watchful.new
+ advice_called = false
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method do |jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ end
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept an :advice => Proc parameter indicating the advice to use." do
+ watchful = Watchful.new
+ advice_called = false
+ advice = Proc.new {|jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ }
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advice => advice
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept a :call => Proc parameter as a synonym for :advice." do
+ watchful = Watchful.new
+ advice_called = false
+ advice = Proc.new {|jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ }
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :call => advice
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept a :invoke => Proc parameter as a synonym for :advice." do
+ watchful = Watchful.new
+ advice_called = false
+ advice = Proc.new {|jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ }
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :invoke => advice
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should accept a :advise_with => Proc parameter as a synonym for :advice." do
+ watchful = Watchful.new
+ advice_called = false
+ advice = Proc.new {|jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ }
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advise_with => advice
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should ignore all other advice parameters if a block is given." do
+ watchful = Watchful.new
+ advice_called = false
+ advice1 = Proc.new {|jp, *args| fail "advice1"}
+ advice2 = Proc.new {|jp, *args| fail "advice2"}
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advice => advice1, :invoke => advice2 do |jp, *args|
+ advice_called = true
+ end
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should be_true
+ aspect.unadvise
+ end
+
+ it "should ignore all but the last advice parameter, using any synonym, if there is no advice block." do
+ watchful = Watchful.new
+ advice_called = false
+ advice1 = Proc.new {|jp, *args|
+ advice_called = true
+ jp.should_not be_nil
+ args.size.should == 4
+ args.should == [:a1, :a2, :a3, {:h1 => 'h1', :h2 => 'h2'}]
+ }
+ advice2 = Proc.new {|jp, *args| raise "should not be called"}
+ aspect = Aspect.new :before, :object => watchful, :methods => :public_watchful_method, :advice => advice2, :advice => advice1
+ watchful.public_watchful_method :a1, :a2, :a3, :h1 => 'h1', :h2 => 'h2'
+ advice_called.should be_true
+ aspect.unadvise
+ end
+end
+
+
+class ExcludeBase
+ def doit; end
+ def initialize arg; @value = arg; end
+ attr_accessor :value
+ def inspect; "(#{self.class}: #{@value})"; end
+ def eql? other
+ return false unless other.kind_of?(self.class)
+ @value == other.value
+ end
+ alias_method :==, :eql?
+end
+class DontExclude1 < ExcludeBase; end
+class DontExclude2 < ExcludeBase; end
+class Exclude1 < ExcludeBase; end
+class Exclude2 < ExcludeBase; end
+
+class Exclude1b < Exclude1
+ def initialize arg; super(arg); end
+ def doit2; end
+end
+class Exclude1c < Exclude1
+ def initialize arg; super(arg); end
+ def doit3; end
+end
+
+describe Aspect, "#new with a :type(s) parameter and an :exclude_type(s) parameter" do
+ def do_exclude_types exclude_type_sym
+ included_types = [DontExclude1, DontExclude2]
+ excluded_types = [Exclude1, Exclude2]
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :types => (included_types + excluded_types), exclude_type_sym => excluded_types, :methods => :doit do |jp, *args|
+ advice_called = true
+ excluded_types.should_not include(jp.target_type)
+ end
+ included_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should be_true
+ end
+ excluded_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+
+ it "should accept :type(s) => [T1, ...], :exclude_type(s) => [T2, ...] and exclude join points in the excluded types" do
+ do_exclude_types :exclude_types
+ end
+
+ it "should accept :exclude_type as a synonym for :exclude_types" do
+ do_exclude_types :exclude_type
+ end
+end
+
+
+describe Aspect, "#new with a :object(s) parameter and an :exclude_object(s) parameter" do
+ def do_exclude_objects exclude_object_sym
+ dontExclude1 = DontExclude1.new(1)
+ dontExclude2 = DontExclude1.new(2)
+ exclude1 = DontExclude1.new(3)
+ exclude2 = DontExclude1.new(4)
+ included_objects = [dontExclude1, dontExclude2]
+ excluded_objects = [exclude1, exclude2]
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :objects => (included_objects + excluded_objects), exclude_object_sym => excluded_objects, :methods => :doit do |jp, *args|
+ advice_called = true
+ excluded_objects.should_not include(jp.context.advised_object)
+ end
+ included_objects.each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should be_true
+ end
+ excluded_objects.each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+
+ it "should accept :object(s) => [o1, ...], :exclude_object(s) => [o2, ...] and exclude join points in the excluded objects" do
+ do_exclude_objects :exclude_objects
+ end
+
+ it "should accept :exclude_object as a synonym for :exclude_objects" do
+ do_exclude_objects :exclude_object
+ end
+end
+
+
+describe Aspect, "#new with a :pointcut(s), :type(s), :object(s), and :method(s) parameter and an :exclude_join_point(s) parameter" do
+ def do_exclude_join_points exclude_join_points_sym
+ dontExclude1 = DontExclude1.new(1)
+ dontExclude2 = DontExclude1.new(2)
+ exclude1 = DontExclude1.new(3)
+ exclude2 = DontExclude1.new(4)
+ included_objects = [dontExclude1, dontExclude2]
+ excluded_objects = [exclude1, exclude2]
+ excluded_join_point1 = JoinPoint.new :object => exclude1, :method => :doit
+ excluded_join_point2 = JoinPoint.new :object => exclude2, :method => :doit
+ excluded_join_points = [excluded_join_point1, excluded_join_point2]
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :objects => (included_objects + excluded_objects), exclude_join_points_sym => excluded_join_points, :methods => :doit do |jp, *args|
+ advice_called = true
+ excluded_objects.should_not include(jp.context.advised_object)
+ end
+
+ included_objects.each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should be_true
+ end
+ excluded_objects.each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+
+ it "should accept :exclude_join_point as a synonym for :exclude_join_points" do
+ do_exclude_join_points :exclude_join_point
+ end
+
+ it "should accept :object(s) => [o1, ...], :exclude_join_point(s) => [jps], where [jps] are the list of join points for the objects and methods to exclude" do
+ do_exclude_join_points :exclude_join_points
+ end
+
+ it "should accept :type(s) => [T1, ...], :exclude_join_point(s) => [jps], where [jps] are the list of join points for the types and methods to exclude" do
+ included_types = [DontExclude1, DontExclude2]
+ excluded_types = [Exclude1, Exclude2]
+ excluded_join_point1 = JoinPoint.new :type => Exclude1, :method => :doit
+ excluded_join_point2 = JoinPoint.new :type => Exclude2, :method => :doit
+ excluded_join_points = [excluded_join_point1, excluded_join_point2]
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :types => (included_types + excluded_types), :exclude_join_points => excluded_join_points, :methods => :doit do |jp, *args|
+ advice_called = true
+ excluded_types.should_not include(jp.target_type)
+ end
+
+ included_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should be_true
+ end
+ excluded_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+
+ it "should accept :pointcut(s) => [P1, ...], :exclude_join_point(s) => [jps], where [jps] are the list of join points for the types and methods to exclude" do
+ included_types = [DontExclude1, DontExclude2]
+ excluded_types = [Exclude1, Exclude2]
+ excluded_join_point1 = JoinPoint.new :type => Exclude1, :method => :doit
+ excluded_join_point2 = JoinPoint.new :type => Exclude2, :method => :doit
+ excluded_join_points = [excluded_join_point1, excluded_join_point2]
+ pointcut1 = Pointcut.new :types => included_types, :method => :doit
+ pointcut2 = Pointcut.new :types => excluded_types, :method => :doit
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_join_points => excluded_join_points do |jp, *args|
+ advice_called = true
+ excluded_types.should_not include(jp.target_type)
+ end
+ included_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should be_true
+ end
+ excluded_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+end
+
+describe Aspect, "#new with a :pointcut(s), :type(s), :object(s), and :method(s) parameter and an :exclude_pointcut(s) parameter" do
+ def do_exclude_pointcuts exclude_pointcuts_sym
+ dontExclude1 = DontExclude1.new(1)
+ dontExclude2 = DontExclude1.new(2)
+ exclude1 = DontExclude1.new(3)
+ exclude2 = DontExclude1.new(4)
+ included_objects = [dontExclude1, dontExclude2]
+ excluded_objects = [exclude1, exclude2]
+ excluded_pointcut1 = Pointcut.new :object => exclude1, :method => :doit
+ excluded_pointcut2 = Pointcut.new :object => exclude2, :method => :doit
+ excluded_pointcuts = [excluded_pointcut1, excluded_pointcut2]
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :objects => (included_objects + excluded_objects), exclude_pointcuts_sym => excluded_pointcuts, :methods => :doit do |jp, *args|
+ advice_called = true
+ excluded_objects.should_not include(jp.context.advised_object)
+ end
+
+ included_objects.each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should be_true
+ end
+ excluded_objects.each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+
+ it "should accept :exclude_pointcut as a synonym for :exclude_pointcuts" do
+ do_exclude_pointcuts :exclude_pointcut
+ end
+
+ it "should accept :object(s) => [o1, ...], :exclude_pointcut(s) => [pcs], where [pcs] are the list of pointcuts for the objects and methods to exclude" do
+ do_exclude_pointcuts :exclude_pointcuts
+ end
+
+ it "should accept :type(s) => [T1, ...], :exclude_pointcut(s) => [pcs], where [pcs] are the list of pointcuts for the types and methods to exclude" do
+ included_types = [DontExclude1, DontExclude2]
+ excluded_types = [Exclude1, Exclude2]
+ excluded_pointcut1 = Pointcut.new :type => Exclude1, :method => :doit
+ excluded_pointcut2 = Pointcut.new :type => Exclude2, :method => :doit
+ excluded_pointcuts = [excluded_pointcut1, excluded_pointcut2]
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :types => (included_types + excluded_types), :exclude_pointcuts => excluded_pointcuts, :methods => :doit do |jp, *args|
+ advice_called = true
+ excluded_types.should_not include(jp.target_type)
+ end
+
+ included_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should be_true
+ end
+ excluded_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+
+ it "should accept :pointcut(s) => [P1, ...], :exclude_pointcut(s) => [pcs], where [pcs] are the list of pointcuts for the types and methods to exclude" do
+ included_types = [DontExclude1, DontExclude2]
+ excluded_types = [Exclude1, Exclude2]
+ excluded_pointcut1 = Pointcut.new :type => Exclude1, :method => :doit
+ excluded_pointcut2 = Pointcut.new :type => Exclude2, :method => :doit
+ excluded_pointcuts = [excluded_pointcut1, excluded_pointcut2]
+ pointcut1 = Pointcut.new :types => included_types, :method => :doit
+ pointcut2 = Pointcut.new :types => excluded_types, :method => :doit
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_pointcuts => excluded_pointcuts do |jp, *args|
+ advice_called = true
+ excluded_types.should_not include(jp.target_type)
+ end
+ included_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should be_true
+ end
+ excluded_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+end
+
+describe Aspect, "#new with type-based :pointcut(s) and :exclude_type(s) parameter" do
+
+ it "should accept :pointcut(s) => [P1, ...], :exclude_type(s) => [types], where join points with [types] are excluded" do
+ included_types = [DontExclude1, DontExclude2]
+ excluded_types = [Exclude1, Exclude2]
+ pointcut1 = Pointcut.new :types => included_types, :method => :doit
+ pointcut2 = Pointcut.new :types => excluded_types, :method => :doit
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_types => excluded_types do |jp, *args|
+ advice_called = true
+ excluded_types.should_not include(jp.target_type)
+ end
+
+ included_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should be_true
+ end
+ excluded_types.each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+end
+
+
+describe Aspect, "#new with object-based :pointcut(s) and :exclude_object(s) or :exclude_method(s) parameter" do
+
+ it "should accept :pointcut(s) => [P1, ...], :exclude_object(s) => [objects], where join points with [objects] are excluded" do
+ dontExclude1 = DontExclude1.new(1)
+ dontExclude2 = DontExclude1.new(2)
+ exclude1 = DontExclude1.new(3)
+ exclude2 = DontExclude1.new(4)
+ included_objects = [dontExclude1, dontExclude2]
+ excluded_objects = [exclude1, exclude2]
+ pointcut1 = Pointcut.new :objects => included_objects, :method => :doit
+ pointcut2 = Pointcut.new :objects => excluded_objects, :method => :doit
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new :before, :pointcuts => [pointcut1, pointcut2], :exclude_objects => excluded_objects do |jp, *args|
+ advice_called = true
+ excluded_objects.should_not include(jp.context.advised_object)
+ end
+ included_objects.each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should be_true
+ end
+ excluded_objects.each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+end
+
+describe Aspect, "#new with :method(s) and :exclude_method(s) parameter" do
+ before :each do
+ @dontExclude1 = DontExclude1.new(1)
+ @dontExclude2 = DontExclude1.new(2)
+ @exclude1 = DontExclude1.new(3)
+ @exclude2 = DontExclude1.new(4)
+ @exclude1c = Exclude1c.new(5)
+ @included_objects = [@dontExclude1, @dontExclude2, @exclude1, @exclude2]
+ @excluded_objects = [@exclude1c]
+ @included_types = [DontExclude1, DontExclude2, Exclude1, Exclude2]
+ @excluded_types = [Exclude1c]
+ @excluded_methods = [:doit3]
+ @pointcut1 = Pointcut.new :objects => @included_objects, :method => /doit/
+ @pointcut2 = Pointcut.new :objects => @excluded_objects, :method => /doit/
+ @pointcut3 = Pointcut.new :types => @included_types, :method => /doit/
+ @pointcut4 = Pointcut.new :types => @excluded_types, :method => /doit/
+ end
+
+ def do_method_exclusion parameter_hash, types_were_specified
+ parameter_hash[:before] = ''
+ parameter_hash[:exclude_method] = :doit3
+ aspect = nil
+ advice_called = false
+ aspect = Aspect.new parameter_hash do |jp, *args|
+ advice_called = true
+ @excluded_methods.should_not include(jp.method_name)
+ end
+ if types_were_specified
+ (@included_types + @excluded_types).each do |type|
+ advice_called = false
+ type.new(1).doit
+ advice_called.should be_true
+ end
+ @excluded_types.each do |type|
+ advice_called = false
+ type.new(1).doit3
+ advice_called.should_not be_true
+ end
+ end
+ (@included_objects + @excluded_objects).each do |object|
+ advice_called = false
+ object.doit
+ advice_called.should be_true
+ end
+ @excluded_objects.each do |object|
+ advice_called = false
+ object.doit3
+ advice_called.should_not be_true
+ end
+ aspect.unadvise
+ end
+
+ it "should accept :exclude_method as a synonym for exclude_methods" do
+ parameter_hash = { :pointcuts => [@pointcut1, @pointcut2, @pointcut3, @pointcut4] }
+ do_method_exclusion parameter_hash, true
+ end
+
+ it "should accept :pointcut(s) => [P1, ...], :exclude_method(s) => [methods], where join points with [methods] are excluded" do
+ parameter_hash = { :pointcuts => [@pointcut1, @pointcut2, @pointcut3, @pointcut4] }
+ do_method_exclusion parameter_hash, true
+ end
+
+ it "should accept :type(s) => ..., :method(s) => ..., :exclude_method(s) => [methods], where join points with [methods] are excluded" do
+ parameter_hash = { :types => (@included_types + @excluded_types), :methods => /doit/ }
+ do_method_exclusion parameter_hash, true
+ end
+
+ # it "should accept :object(s) => ..., :method(s) => ..., :exclude_method(s) => [methods], where join points with [methods] are excluded" do
+ # pending "bug fix"
+ # Aspect.echo = true
+ # parameter_hash = { :objects => (@included_objects + @excluded_objects), :methods => /doit/ }
+ # do_method_exclusion parameter_hash, false
+ # Aspect.echo = false
+ # end
+ #
+ # def do_method_exclusion2 parameter_hash, types_were_specified
+ # parameter_hash[:before] = ''
+ # parameter_hash[:exclude_method] = :doit3
+ # parameter_hash[:method] = /doit/
+ # aspect = nil
+ # advice_called = false
+ # aspect = Aspect.new parameter_hash do |jp, *args|
+ # advice_called = true
+ # @excluded_methods.should_not include(jp.method_name)
+ # end
+ # (@excluded_objects).each do |object|
+ # advice_called = false
+ # object.doit
+ # advice_called.should be_true
+ # end
+ # aspect.unadvise
+ # end
+ #
+ # def buggy parameter_hash
+ # parameter_hash[:before] = ''
+ # parameter_hash[:exclude_method] = :doit3
+ # aspect = Aspect.new parameter_hash do |jp, *args|
+ # end
+ # @excluded_objects.each do |object|
+ # object.doit
+ # end
+ # aspect.unadvise
+ # end
+ #
+ # it "#15202 bug..." do
+ # pending "bug fix"
+ # @pointcut5 = Pointcut.new :types => [Exclude1, Exclude1c], :method => /doit/
+ # parameter_hash = { :pointcuts => [@pointcut5] } #[@pointcut1, @pointcut2, @pointcut3, @pointcut4] }
+ # buggy parameter_hash
+ # parameter_hash = { :objects => (@excluded_objects), :method => /doit/ }
+ # buggy parameter_hash
+ # end
+end
\ No newline at end of file