diff options
Diffstat (limited to 'spec/ruby/core/module/define_method_spec.rb')
-rw-r--r-- | spec/ruby/core/module/define_method_spec.rb | 138 |
1 files changed, 132 insertions, 6 deletions
diff --git a/spec/ruby/core/module/define_method_spec.rb b/spec/ruby/core/module/define_method_spec.rb index 0cb2ab140c..e04bb87ceb 100644 --- a/spec/ruby/core/module/define_method_spec.rb +++ b/spec/ruby/core/module/define_method_spec.rb @@ -133,6 +133,17 @@ describe "Module#define_method when name is not a special private name" do klass.should have_public_instance_method(:baz) end end + + it "sets the method owner for a dynamically added method with a different original owner" do + mixin_module = Module.new do + def bar; end + end + + foo = Object.new + foo.singleton_class.define_method(:bar, mixin_module.instance_method(:bar)) + + foo.method(:bar).owner.should == foo.singleton_class + end end describe "passed a block" do @@ -219,18 +230,55 @@ describe "Module#define_method" do o.block_test2.should == o end + it "raises TypeError if name cannot converted to String" do + -> { + Class.new { define_method(1001, -> {}) } + }.should raise_error(TypeError, /is not a symbol nor a string/) + + -> { + Class.new { define_method([], -> {}) } + }.should raise_error(TypeError, /is not a symbol nor a string/) + end + + it "converts non-String name to String with #to_str" do + obj = Object.new + def obj.to_str() "foo" end + + new_class = Class.new { define_method(obj, -> { :called }) } + new_class.new.foo.should == :called + end + + it "raises TypeError when #to_str called on non-String name returns non-String value" do + obj = Object.new + def obj.to_str() [] end + + -> { + Class.new { define_method(obj, -> {}) } + }.should raise_error(TypeError, /can't convert Object to String/) + end + it "raises a TypeError when the given method is no Method/Proc" do -> { Class.new { define_method(:test, "self") } - }.should raise_error(TypeError) + }.should raise_error(TypeError, "wrong argument type String (expected Proc/Method/UnboundMethod)") -> { Class.new { define_method(:test, 1234) } - }.should raise_error(TypeError) + }.should raise_error(TypeError, "wrong argument type Integer (expected Proc/Method/UnboundMethod)") -> { Class.new { define_method(:test, nil) } - }.should raise_error(TypeError) + }.should raise_error(TypeError, "wrong argument type NilClass (expected Proc/Method/UnboundMethod)") + end + + it "uses provided Method/Proc even if block is specified" do + new_class = Class.new do + define_method(:test, -> { :method_is_called }) do + :block_is_called + end + end + + new_class.new.test.should == :method_is_called end it "raises an ArgumentError when no block is given" do @@ -350,6 +398,14 @@ describe "Module#define_method" do object2.other_cool_method.should == "data is foo" end + it "accepts a proc from a Symbol" do + symbol_proc = :+.to_proc + klass = Class.new do + define_method :foo, &symbol_proc + end + klass.new.foo(1, 2).should == 3 + end + it "maintains the Proc's scope" do class DefineMethodByProcClass in_scope = true @@ -443,6 +499,33 @@ describe "Module#define_method" do Class.new { define_method :bar, m } }.should raise_error(TypeError, /can't bind singleton method to a different class/) end + + it "defines a new method with public visibility when a Method passed and the class/module of the context isn't equal to the receiver of #define_method" do + c = Class.new do + private def foo + "public" + end + end + + object = c.new + object.singleton_class.define_method(:bar, object.method(:foo)) + + object.bar.should == "public" + end + + it "defines the new method according to the scope visibility when a Method passed and the class/module of the context is equal to the receiver of #define_method" do + c = Class.new do + def foo; end + end + + object = c.new + object.singleton_class.class_eval do + private + define_method(:bar, c.new.method(:foo)) + end + + -> { object.bar }.should raise_error(NoMethodError) + end end describe "Module#define_method" do @@ -641,7 +724,7 @@ describe "Module#define_method" do end end -describe "Method#define_method when passed a Method object" do +describe "Module#define_method when passed a Method object" do before :each do @klass = Class.new do def m(a, b, *c) @@ -666,7 +749,7 @@ describe "Method#define_method when passed a Method object" do end end -describe "Method#define_method when passed an UnboundMethod object" do +describe "Module#define_method when passed an UnboundMethod object" do before :each do @klass = Class.new do def m(a, b, *c) @@ -691,7 +774,7 @@ describe "Method#define_method when passed an UnboundMethod object" do end end -describe "Method#define_method when passed a Proc object" do +describe "Module#define_method when passed a Proc object" do describe "and a method is defined inside" do it "defines the nested method in the default definee where the Proc was created" do prc = nil @@ -715,3 +798,46 @@ describe "Method#define_method when passed a Proc object" do end end end + +describe "Module#define_method when passed a block" do + describe "behaves exactly like a lambda" do + it "for return" do + Class.new do + define_method(:foo) do + return 42 + end + end.new.foo.should == 42 + end + + it "for break" do + Class.new do + define_method(:foo) do + break 42 + end + end.new.foo.should == 42 + end + + it "for next" do + Class.new do + define_method(:foo) do + next 42 + end + end.new.foo.should == 42 + end + + it "for redo" do + Class.new do + result = [] + define_method(:foo) do + if result.empty? + result << :first + redo + else + result << :second + result + end + end + end.new.foo.should == [:first, :second] + end + end +end |